Docker Dockerfile

Dockerfile

如果你想从一个基础镜像开始构建一个自定义的镜像,可以选择一步步的操作,也可以选择编写一个配置脚本,然后一条docker build命令完成构建,显然使用配置脚本的方式能更好地应对需求的变更,这里的配置脚本也就时Dockerfile。

  • Dockerfile文件用于构建镜像
  • Dockfile语法由两部分构成分别是注释、指令+参数
  • Dockerfile的指令时忽略大小写的,建议使用小写。
  • Dockerfile注释使用#标记
  • Dockerfile每行只支持一条指令

例如:Swoft默认的Dockerfile文件

FROM php:7.1

MAINTAINER huangzhhui <h@swoft.org>

# Version
ENV PHPREDIS_VERSION 4.0.0
ENV HIREDIS_VERSION 0.13.3
ENV SWOOLE_VERSION 4.0.3

# Timezone
RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
    && echo 'Asia/Shanghai' > /etc/timezone

# Libs
RUN apt-get update \
    && apt-get install -y \
        curl \
        wget \
        git \
        zip \
        libz-dev \
        libssl-dev \
        libnghttp2-dev \
        libpcre3-dev \
    && apt-get clean \
    && apt-get autoremove

# Composer
RUN curl -sS https://getcomposer.org/installer | php \
    && mv composer.phar /usr/local/bin/composer \
    && composer self-update --clean-backups

# PDO extension
RUN docker-php-ext-install pdo_mysql

# Bcmath extension
RUN docker-php-ext-install bcmath

# Redis extension
RUN wget http://pecl.php.net/get/redis-${PHPREDIS_VERSION}.tgz -O /tmp/redis.tar.tgz \
    && pecl install /tmp/redis.tar.tgz \
    && rm -rf /tmp/redis.tar.tgz \
    && docker-php-ext-enable redis

# Hiredis
RUN wget https://github.com/redis/hiredis/archive/v${HIREDIS_VERSION}.tar.gz -O hiredis.tar.gz \
    && mkdir -p hiredis \
    && tar -xf hiredis.tar.gz -C hiredis --strip-components=1 \
    && rm hiredis.tar.gz \
    && ( \
        cd hiredis \
        && make -j$(nproc) \
        && make install \
        && ldconfig \
    ) \
    && rm -r hiredis

# Swoole extension
RUN wget https://github.com/swoole/swoole-src/archive/v${SWOOLE_VERSION}.tar.gz -O swoole.tar.gz \
    && mkdir -p swoole \
    && tar -xf swoole.tar.gz -C swoole --strip-components=1 \
    && rm swoole.tar.gz \
    && ( \
        cd swoole \
        && phpize \
        && ./configure --enable-async-redis --enable-mysqlnd --enable-openssl --enable-http2 \
        && make -j$(nproc) \
        && make install \
    ) \
    && rm -r swoole \
    && docker-php-ext-enable swoole

ADD . /var/www/swoft

WORKDIR /var/www/swoft

RUN composer install --no-dev \
    && composer dump-autoload -o \
    && composer clearcache

EXPOSE 80

ENTRYPOINT ["php", "/var/www/swoft/bin/swoft", "start"]

操作流程

  1. 创建一个Dockerfile文件
  2. 编写Dockerfile指令
  3. 使用docker build构建镜像
  4. 使用docker run运行容器
  5. 检查镜像与容器

构建流程

构建流程

指令组成

  • 基础镜像信息:FROM
  • 维护者信息:MAINTAINER
  • 镜像操作指令:RUNCOPYADDEXPOSEWORKINGUSERVOLUME...
  • 容器启动时执行指令:CMDENTRYPOINT

指令解析

ADD

ADD <源文件><容器目录>

ADD指令会从源系统的文件系统上复制文件到目标容器的文件系统,若源系统是一个URL,那么该URL的内容将被下载并复制到容器中。

如果本地源路径的文件是一个tar压缩文件的话,压缩格式为gzipbzip2xz的情况下,ADD指令将会自动解压到目标路径,但是来自URL的远程文件时不会被解压的。

例如:ADD application.yml /etc/service

CMD

CMD <命令><参数>

CMD指令只要是为一个正在运行的容器提供默认的执行命令,如果存在多个CMD指令,那么只有最后一个会被执行。如果在容器运行时指定了命令,则CMD指定的默认命令会被替代。

CMD指令用于执行特定的命令,命令不是在镜像构建过程中执行,而是在用镜像构建容器后被调用。

CMD有三种格式:

  • CMD ["executable", "parameter1", "parameter2"]
    常见执行形式:CMD ["echo", "hello world"]
  • CMD ["parameter1", "parameter2"]
    以JSON数组的形式将两个参数存储起来,在指定了ENTRYPOINT入口点指定后,使用CMD指定具体的参数,此处必须用双引号将变量包裹。
  • CMD command parameter1 parameter2
    使用Shell形式:CMD echo "hello world"

ENTRYPOINT

ENTRYPOINT 

ENTRYPOINT指令的格式和RUN指令格式一样,分为exec格式和shell格式,与CMD指令目的一样,都是在指定容器启动程序及参数。

ENTRYPOINT在运行时可以替代,不过比CMD要略显繁琐,需要通过docker run的参数--entrypoint来指定。当指定了ENTRYPOINT后,CMD的含义就发生了改变,不再是直接运行其命令,而是将CMD的内容作为参数传递给ENTRYPOINT指令。

ENTRYPOINT指令配置容器启动后执行的命令,不会被docker run命令提供的参数覆盖。

每个Dockfile中只能有一个ENTERPINT入口点,当指定多个时只有最后一个起效。

ENTERPOINT入口点帮助你配置一个容器使之可执行化,如果结合CMD使用时可从CMD命令中删除"application"而仅仅保留参数,参数将传递给ENTERPOINT命令。

ENV

ENV <键名><键值>

ENV指令用于设置键值对的环境变量,可在容器内被脚本或程序调用。并且可以引用已经存在的环境变量,例如HOME、HOSTNAME、PATH。

Dockerfile中ENV支持以下变量的访问:ADD、COPY、ENV、EXPOSE、FROM、LABEL、STOPSIGNAL、USER、VOLUME、WORKDIR。

例如:ENV SERVER_WORKS 4

EXPOSE

EXPOSE <端口>

EXPOSE指令用于指定容器在运行时监听的端口,使容器内的应用可通过端口与外界交互。

EXPOSE指令用于暴露镜像的端口供宿主机(主机)做映射,启动镜像时,可使用-P参数将镜像端口与宿主机的随机端口做映射。

默认情况下,EXPOSE指定的时TCP端口,若要指定监听UDP端口:EXPOSE 80/udp

FROM

FROM <镜像名称>
FROM <镜像名称>[:<标签名称>]

每个Dockerfile必须以FROM指令开头,FROM指明了当前镜像创建的基镜像,也就是说每个镜像必须基于一个已经存在的镜像才能创建。

FROM指令后面直接跟基镜像的名称或【镜像名称+标签】,镜像名称和标签可以去DockerHub或使用docker search keyword进行搜索。

FROM指令定义使用哪个基础镜像启动构建流程,基本镜像可以为任意镜像。如果基础镜像没有被发现,Docker将试图从docker image index来查找该镜像。

MAINTAINER

MAINTAINER <作者名称>

MAINTAINER指令用于声明作者,建议放在FROM命令后,理论上可放在任意位置。MAINTAINER在新版中已经被废弃,可使用LABEL来替代进行声明。

例如:MAINTAINER author_name

指定镜像作者与电子邮箱

例如:MAINTAINER junchow "1021013123@qq.com"

RUN

RUN <命令>

RUN指令是Dockerfile执行命令的核心部分,它接收命令作为参数并用于创建镜像,会在之前的Commit的层之上形成新的层。

RUN指令在当前镜像的顶层中执行命令并提交结果,新产生的镜像用于下一步的Dockerfile。

例如:RUN aptitude install -y docker

USER

USER <user>[:<group>]

USER指令用于设置运行容器的用户ID,主要是为Dockerfile中全部RUN、CMD、ENTRYPOINT设置运行镜像Image时使用的用户名或UID。这个用户或组必须事先在系统中存在,若不存在则下一层镜像会以root用户进行执行。

例如:USER 751

VOLUME

VOLUME <宿主机目录>

VOLUME旨在创建一个具有名称的挂载点,用于让容器访问宿主机上的目录。容器在运行时尽量保持存储层不发生数据写入操作。一个卷可以存在于一个或多个容器的特定目录,这个目录可以绕过联合文件系统,并提供数据共享或数据持久化功能。卷可以在容器间共享或重用,对卷的修改是即时生效的。对卷的修改不会对新的镜像产生影响,卷会一直存在直到没有容器使用它。

例如:VOLUME /share

可以使用数组的形式指定多个卷

例如:VOLUME ['data', 'test']

VOLUME可以在创建容器时声明

例如:docker run -it -v /share --name mycontainer chatdevops

WORKING

WORKING <CMD命令的运行目录>

WOKKING指令用于设置CMD指定的命令的运行目录

例如:WORKING ~/

CMD与ENTRYPOINT的区别

CMD指令与ENTRYPOINT指令有什么异同点呢?

CMD和ENTRYPOINT都可以作为容器启动时执行的命令,区别在于:

  1. CMD指令会被docker run命令覆盖,ENTRYPOINT则不会。

如果设置CMD ['/bin/bash']ENTRYPOINT ['/bin/bash']后,再使用docker run -it image启动容器时会自动进入容器内部的交互终端,效果等同于docker run -it image /bin/bash

如果使用docker run -it image /bin/ps启动镜像,此时CMD指定的参数就会被覆盖,转而执行/bin/ps命令。而ENTRYPOINT指定的参数则不会被覆盖,它会把docker run的参数作为ENTRYPOINT执行命令的参数。

  1. 当CMD和ENTRYPOINT都存在时

当CMD和ENTRYPOINT指令都存在时,CMD指令会变成ENTRYPOINT的参数,并且CMD提供的参数会被docker run覆盖。

未完待续...

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,826评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,968评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,234评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,562评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,611评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,482评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,271评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,166评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,608评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,814评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,926评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,644评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,249评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,866评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,991评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,063评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,871评论 2 354

推荐阅读更多精彩内容