Docker Dockerfile

4933701-1d9fe0e2866aa465.png
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. 检查镜像与容器

构建流程

4933701-b594c914181f439a.png
构建流程

指令组成

  • 基础镜像信息: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覆盖。

未完待续...

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值