使用Dockerfile创建镜像
Dockerfile是一个文本格式的配置文件,我们可以利用Dockerfile来快速的创建一个自定义的镜像。
基本结构
Dockerfile由一行命令语句组成,并且支持以#开头的注释 一般包括四个部分:基础镜像信息,维护者信息,镜像操作指令,容器启动时执行指令,如下一个案例
# This Dockerfile uses the ubuntu image
# VERSION 2 - EDITION 1
# Author: docker_user
# Command format: Instruction [ arguments / command] . .
# Base image to use, this must be set as the first line
FROM ubuntu
# Maintainer: docker_user < docker_user at email. com> ( @docker_user )
MAINTAINER docker_user docker_user@email . com
# Commands to update the image
RUN echo "deb http://archive.ubuntu.com/ubuntu/ raring main universe" >> / etc/ apt/
sources. list
RUN apt- get update && apt- get install - y nginx
RUN echo "\ndaemon off;" >> / etc/ nginx/ nginx. conf
# Commands when creating a new container
CMD / usr/ sbin/ nginx
如上是一个官网的Demo,一开始指定所基于的镜像名称,之后是维护者的信息,后面才是镜像操作的指令,例如RUN指令将对镜像执行跟随在后面的命令,CMD用来指定运行容器时候的操作命令。 如下是一个更复杂一点的案例,基于buildpack-deps:jessie-scm基础镜像,安装Golang相关环境,制作一个GO语言的运行环境镜像(先看看就行):
FROM buildpack- deps: jessie- scm
# gcc for cgo
RUN apt- get update && apt- get install - y -- no- install- recommends \
g++ \
gcc \
libc6- dev \
make \
&& rm - rf / var/ lib/ apt/ lists
指令说明
FROM
指定所创建镜像的基础镜像,如果本地不存在,默认去Docker Hub上下载,格式:FROM < image> 任何一个Dockerfile中第一条指令必须是FROM,并且,如果在同一个Dockerfile中创建多个镜像,可以用多个FROM指令
MAINTAINER
指定维护者信息,格式MAINTAINER< name>。信息会写入生成镜像的Author属性域中例如:
MAINTAINER ljmadmin@docker . com
RUN
运行指定命令格式如下 上面第一个命令默认将在shell中断中运行,即 /bin/sh -C ,后面的使用exec执行不会启动shell环境 每一条RUN指令将在当前镜像的基础上执行指定的命令,并且提交为新的进行,当命令比较长的时候,可以用\ 来换行,比如:
RUN < command> 或者 RUN [ "executable" , "param1" , "param2" ] ,
RUN apt- get update \
&& apt- get install - y libsnappy- dev zliblg- dev libbz2- dev \
&& rm - rf / var/ cache/ apt
CMD
CMD指令用来指定启动容器时候默认执行的命令,他支持三种格式:
CMD[“executable”, “param1”, “param2”] 使用exec执行,是推荐使用的方式 CMD command param1 param2 在/bin/sh 中执行,提供给需要交互的应用 CMD [“param1”, “param2”]提供给ENTRYPOINT的默认数 每个DOckerfile只能有一条CMD命令,如果指定多条,最后一条覆盖之前的
LABEL
LABEL指令用来指定生成镜像的元数据标签信息 格式为如下例如
LABEL< key> = < value> < key> = < value> . . . .
LABEL version= "1.0"
LABEL description= "This text illustrates \ that label-values can span multiple lines."
EXPOSE
EXPOSE < port> [ < port> . . . . . . ]
EXPOSE 22 80 8443
改指令只是起到声明作用,不会自动完成端口映射 启动容器时候需要使用-P,Docker主机会自动分配一个宿主机临时端口转发到指定的端口,使用-p,则可以具体的指定哪个宿主机本地端口会映射过来。
ENV
指定环境变量,在镜像生成过程中会被后续RUN指令使用,在镜像启动的容器中也会存在 格式…。如下:
ENV < key> < value> 或者 EVN < key> = < value>
ENV PG_MAJOR 9.3
ENV PG_VERSION 9.3 .4
RUN curl - SL http: / / example. com/ postgres- $PG_VERSION. tar. xz | tar - xJC / usr/ src/
postgress && …
ENV PATH / usr/ local/ postgres- $PG_MAJOR/ bin: $PATH
指令指定的环境变量在运行时可以被覆盖掉,比如docker run --evn< key>=< value>built_image
ADD
该命令将复制指定额< src> 路径下的内容到容器中的< dest> 路径下,格式如下 其中< src> 可以是Dockerfile所在的目录的一个相对路径,也可以是一个URL,还可以是一个tar文件。< desc>可以使镜像内部的绝对路径,或者相对于工作目录的相对路径。
ADD < src> < desc>
COPY
格式如下,复制本地主机的< src> (为Dockerfile所在目录的相对路径,文件,或者目录) 下的内容 到镜像中的< dest> 下。目标路径不存在时候回自动创建 。路径支持正则,当使用本地目录为源目录时候,推荐使用COPY
COPY< src> < desc>
ENTRYPOINT
指定镜像的默认入口命令,该入口命令会在启动容器时候作为命令执行,所有传入值作为改命令的参数,支持如下两种格式
ENTRYPOINT [ "executable" , "param1" , "param2" ] (exec调用执行)
ENTRYPOINT command param1 param2(shell中执行)
每个Dockerfila中只能有一个ENTRYPOINT,当指定过个时候,只有最后一个有效,在运行时候可以被–entrypoint参数覆盖掉,如docker run–entrypoint
VOLUME
创建一个数据卷挂载点, 可以从本地主机或者其他容器挂载数据卷,一般用来存放数据库和需要保存的数据等。格式如下
VULUME [ "/data" ]
USER
指定运行容器时候的用户名或者UID,后续的RUN等指令也会使用指定的用户身份格式如下:
USER daemon
RUN groupadd - r postgres && useradd - r - g postgres postgres
需要临时获取管理员权限可以使用gosu或者sudo
WORKDIR
为后续的RUN,CMD和ENTRYPOINT指令配置工作目录,格式如下
WORKDIR / path/ to/ workdir
WORKDIR / a
WORKDIR b
WORKDIR c
RUN pwd
如上案例,可以使用多个WORKDIR指令,后续命令如果参数是相对路径,则会基于之前命令指定的路径。最终的路径为/a/b/c
ARG
指定一些镜像内使用的参数(例如版本号信息等),这些参数在执行docker build命令时以下格式传入
ARG< name> [ = < default value> ]
docker build-- build- arg< name> = < value>
ONBUILD
配置当所有创建的镜像作为其他镜像的基础镜像时,所执行的创建操作指令,格式如下:
ONBUILD [ INSTRUCTION]
[ . . . ]
ONBUILD ADD . / app/ src
ONBUILD RUN / usr/ local/ bing/ python- build -- dir / app/ src
[ . . . ]
如果基于image-A创建新的镜像时候,新的Dockerfile使用FROM image-A指定基础进行,会自动执行ONBUILD指令的内容,等价于在后面添加了两条指令,如下:
FROM image- A
#Automatically run the following
ADD . / app/ src
RUN / usr/ local/ bin/ python- build -- dir / app/ src
使用ONBUILD指令的镜像,推荐在边去中注明,例如ruuby:1.9-onbuild
STOPSIGNAL
指定所创建的镜像启动的容器接受退出的信号值,例如:
STOPSIGNAL signal
HEALTHCHECK
配置所启动容器如何进行健康检查(如何判断健康与否),自Docker1.12开始支持,格式如下:
HEALTHCHECK [ OPTIONS] CMS command : 根据执行命令返回值是否为0 判断
HEALTHCHECK NONE : 禁止基础镜像中的监看检查
OPTION参数支持如下:
__interval=DURATION(默认30s):过多久检查一次 __timeout=DURATION(默认30s):每次检查等待结果的超时 __retries=N(默认为3):如果失败,重试几次才最终确定失败。
创建镜像
编写完Dockerfile后,可以通过docker build命令来创建镜像,基础格式如下:
docker build [ 选项]
如上命令将读取指定路径下(包括子目录)的Dockerfile文件,并将该路劲下所有内容发送给Docker 服务端 ,由服务端来创建镜像,因此除非生成镜像需要,否则一般建议放置Dockerfile的目录为空目录。
如果使用非内容路径下Dockerfile,可以通过-f 选项指定其他路径 要指定生成镜像的便签可以用-t 选项 案例:指定Dockerfile路径/tmp/docker_builder/,并且生成镜像标签为build_repo/first_image,命令如下
docker build - t build_repo/ first_image / temp/ docker_builder
使用.dockerignore文件
上说的,Dockerfile路径下的所有文件都会发到Docker服务端打包,那肯定有响应的规避措施, 我们通过.dockerignore文件(没一行添加一条匹配模式)来让Docker忽略匹配模式路径下的目录和文件。如下:
#comment
* / temo*
*
Dockerfile实战测试
以下将分别通过docker commit命令方式,Dockerfile的方式分别为镜像添加SSH服务并且生成新的镜像文件,来对象两者的区别,
通过docker commit 方式创建镜像
Docker提供了docker commit 命令,支持用户提交自己对指定容器的修改,并且生成新的镜像在本地。格式如下:
docker commit CONTAINER [ REPOSITORY[ : TAG] ]
docker run - it ubuntu: lasted / bin/ bash
apt- get update; apt- get install openssh- server - y
mkdir - p / var/ run/ sshd
/ usr/ sbin/ ssh - D &
sed - ri 's/session required pam_loginuid.so/#session required pam_loginuid.so/g' / etc/ pam. d/ sshd
mkdir root/ . ssh
vi / root/ . ssh/ authorized_keys
vi / run. sh
chmod + x run. sh
#! / bin/ bash
/ usr/ sbin/ sshd - D
exit
docker commit [ CONTAINER ID] sshd: ubuntu
docker run - p 10022 : 22 - d ssh: ubuntu / run. sh
docker ps
ssh 192.168 . *. * - p 10022
使用Dockerfile创建
mkdir sshd_ubuntu
cd / sshd_ubuntu/
touch Dockerfile run. sh
#! / bin/ bash
/ usr/ sbin/ sshd - d
ssh- keygen - t rsa
. . . .
cat ~ / . ssh/ id_rsa. pub > authorized_keys
编写Dockerfile,下面是Dockerfile的内容以及部分的解释信息,可以对比docker commit 命令创建的过程,操作基本一致:
#设置基础镜像
FROM ubuntu: latest
#提供一些作者信息
MAINTAINER ljmadmin ( 645121107 @qq . com)
#下面开始运行更新命令
RUN apt- get update
#安装ssh服务
RUN apt- get install - y openssh- server
RUN mkdir - p / var/ run/ sshd
RUN mkdir - p / root/ . ssh
#取消pam限制
RUN sed - ri 's/session required pam_loginuid.so/#session required pam_loginuid.so/g' / etc/ pam. d/ sshd
#复制配置文件到相应位置,并赋予可执行权限
ADD authorized_keys / root/ . ssh/ authorized_keys
ADD run. sh / run. sh
RUN chmod 755 / run. sh
#开放端口
EXPOSE 22
#设置自启动命令
CMD [ "/run.sh" ]
创建镜像:在sshd_ubuntu目录下使用docker build命令创建镜像,
cd sshd_ubuntu
docker build - t ssh: Dockerfile .
查看本地ssh:Dockerfile镜像已经存在: 测试启动镜像运行容器效果与上面一致
总结
Dockerfile使用前需要熟悉每个命令,多实践,自己写一些简单的案例测试,弄清楚原理在写,Docker Hub官方仓库有很多优秀镜像对应的Dockerfile可以借鉴学习 创建原则有如下几个:
精简镜像用途: 选合适基础镜像 提供足够清晰的命令注释和维护者信息 正确使用版本号码 减少镜像层数 及时删除临时文件和缓存文件 提高生成速度 调整合理的指令顺序 减少外部源干扰
上一篇:Docker中数据管理 下一篇:Docker容器实战思维