Dockerfile与镜像构建

  sre

Dockerfile

Dockerfile是制作镜像的脚本,镜像依据配置文件Dockerfile建立,其中定义了:依赖的基础镜像,自定义操作(修改、安装、构建),容器运行与日志处理等。
写Dockerfile并不等价于Shell脚本,Dockerfile 中每一个指令都会建立一层(最多127层),在其上执行这些命令,执行结束后, commit 这一层的修改,构成新的镜像。
构建镜像时,请确保只添加必需的文件,做到垃圾清理,避免镜像体积臃肿。

常用命令如下:

FROM

Dockerfile必须以FROM开头,定义继承的基础镜像,可以是scratch,即不用任何基础镜像。
推荐在一个极简的基础镜像下继承,如Alpine:A minimal Docker image based on Alpine Linux with a complete package index and only 5 MB in size!

COPY

COPY 将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置,有两种格式,COPY <源路径>... <目标路径>COPY ["<源路径1>",... "<目标路径>"],区别不大。
<源路径> 可以是多个,甚至可以是通配符。
<目标路径> 可以是容器内的绝对路径,也可以是相对于工作目录的相对路径(工作目录可以用 WORKDIR 指令来指定)。目标路径不需要事先创建,如果目录不存在会在复制文件前先行创建缺失目录。
使用 COPY 指令,源文件的各种元数据(属组与权限、时间戳等)都会保留。

ADD

ADD更高级的复制,与COPY基本一致,但增加了一些特性,效率会低一些,在合适的场景下用。
<源路径> 可以是一个 URL ,这种情况下,Docker 引擎会试图去下载这个链接的文件放到 <目标路径> 去。下载后的文件权限自动设置为 600 ,如果这并不是想要的权限,那么还需要增加额外的一层 RUN 进行权限调整,另外,如果下载的是个压缩包,需要解压缩,也一样还需要额外的一层 RUN 指令进行解压缩。所以不如直接使用 RUN 指令,然后使用 wget 或者 curl 工具下载,处理权限、解压缩、然后清理无用文件更合理。因此,这个功能其实并不实用,而且不推荐使用。
如果 <源路径> 为一个 tar 压缩文件的话,压缩格式为 gzip , bzip2 以及 xz 的情况下, ADD 指令将会自动解压缩这个压缩文件到 <目标路径> 去。
尽可能的使用 COPY ,因为 COPY 的语义很明确,就是复制文件而已,而 ADD 则包含了更复杂的功能,其行为也不一定很清晰。ADD 指令会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。
在某些情况下,如果我们真的是希望复制个压缩包而不解压,这时就不可以使用 ADD 命令了。
建议所有的文件复制均使用 COPY 指令,仅在需要自动解压缩的场合使用 ADD 。

RUN

RUN 用来执行命令行命令,分为RUN <命令>RUN ["可执行文件", "参数1", "参数2"]两种格式,区别不大。
尽可能少使用RUN指令,减少镜像的层数,不要去多安装没用的东西。
Dockerfile 支持 Shell 类的行尾添加 \ 的命令换行方式,以及行首 # 进行注释的格式

FROM debian:jessie
RUN buildDeps='gcc libc6-dev make' \
    && apt-get update \
    && apt-get install -y buildDeps \
    && wget -O redis.tar.gz "http://download.redis.io/releases/redis-3.2.5.tar.gz" \
    && mkdir -p /usr/src/redis \
    && tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \
    && make -C /usr/src/redis \
    && make -C /usr/src/redis install \
    && rm -rf /var/lib/apt/lists/* \
    && rm redis.tar.gz \
    && rm -r /usr/src/redis \
    && apt-get purge -y --auto-removebuildDeps

CMD和ENTRYPOINT

CMD是每次运行Docker都要运行的命令,运行后其pid为1,若此命令挂了,容器生命周期结束。
格式:
shell 格式: CMD <命令>
exec 格式: CMD [“可执行文件”, “参数1”, “参数2″…]
参数列表格式: CMD [“参数1”, “参数2”…] 。在指定了 ENTRYPOINT 指令后,用 CMD 指定具体的参数。
注意事项:
– CMD要保持长运行,禁止nohup、&后台等骚操作。
– 默认容器里是不能用service或者systemctl 去管理服务的,除非给容器提权。
– 启动容器的时候,CMD 可以被替代。如 docker run –tid mysql bin/bash。
– CMD和ENTRYPOINT 在dockerfile中各自只能出现一次,如果出现多次,就以最后一个为准。

ENTRYPOINT 入口点
的目的和 CMD 一样,都是在指定容器启动程序及参数。ENTRYPOINT 在运行时也可以替代,不过比 CMD 要略显繁琐,需要通过 docker run 的参数 –entrypoint 来指定。
当指定了 ENTRYPOINT 后, CMD 的含义就发生了改变,不再是直接的运行其命令,而是将CMD 的内容作为参数传给 ENTRYPOINT 指令,换句话说实际执行时,将变为:

EXPOSE

EXPOSE 声明端口,并不会在启动容器的时候进行端口映射。

其他关键字

MAINTAINER 作者、邮箱,会显示在仓库里面。
WORKDIR 指定工作目录。容器启动后,exec 进入容器直接到工作目录下。
USER 指定当前用户,即容器启动后,docker内服务启动用的用户(必须事先建立的用户才可以)。
ENV 环境变量
HEALTHCHECK 健康检查(我倾向用k8s的存活性探针和就绪性探针)

构建镜像

使用 docker build 命令进行镜像构建。其格式为:

docker build [选项] <上下文路径/URL/-> #一般大家习惯性的会使用默认的文件名 Dockerfile ,以及会将其置于镜像构建上下文目录中。
docker build https://github.com/twang2218/gitlab-ce-zh.git#:8.14 #git获取
docker build http://server/context.tar.gz #下载这个包,并自动解压缩,以其作为上下文,开始构建
docker build - < context.tar.gz #从标准输入中读取上下文压缩包进行构建
docker build - < Dockerfile #读取 Dockerfile 进行构建
cat Dockerfile | docker build - #从标准输入中读取 Dockerfile 进行构建

将文件拷贝进容器内:
docker cp 文件路径/filename docker_name:/路径
将docker内的文件拷贝出:
docker docker_name:/路径/filename .
把当前镜像提交镜像:
docker commit -m “my app” 容器id test/myapp:v1

配置文件

推荐:集成配置中心,如superdiamond。
推荐:使用k8s里的configmap的功能
不推荐:将配置文件映射到宿主机上
不允许:配置文件制作进镜像

tips

容器时差处理:

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

字符集问题:

        #centos
         RUN localedef -i zh_CN -f UTF-8 en_US.UTF-8
         ENV LANG en_US.UTF-8
        #ubuntu 
         RUN apt-get clean && apt-get update && apt-get install -y locales \
    locale-gen zh_CN.UTF-8 &&\
    DEBIAN_FRONTEND=noninteractive dpkg-reconfigure locales
         ENV LANG zh_CN.UTF-8
         ENV LANGUAGE zh_CN:zh
         ENV LC_ALL zh_CN.UTF-8

共用系统环境:如映射jdk、python目录到镜像
docker in docker:映射/var/run/docker.sock或使用docker-api。

One Reply to “Dockerfile与镜像构建”

  • FROM java:8
    ADD target/*.jar test.jar
    JAVA_OPTS=-Xms256m -Xmx512m -XX:+UseG1GC -XX:MaxGCPauseMillis=200
    ENTRYPOINT exec java $JAVA_OPTS -jar test.jar
    EXPOSE 9411
    

LEAVE A COMMENT

Captcha Code