https://www.imooc.com/article/details/id/25229html
nginx镜像启动为容器后是为了配置为一个虚拟主机,提供一个虚拟服务。但这个虚拟主机所提供的服务名、监听的端口、家目录等在不一样的环境中是不同的,nginx
但配置文件的格式是固定的,因此把它的配置文件生成一个模板。web
server.conf /etc/nginx/conf.d/ //模板放在/etc/nginx/conf.d/目录下sql
{docker
server_name $NGX_SERVER_NAME; //server_name经过变量$NGC_SERVER获取shell
listen $NGX_IP; $NGINX_PORT;apache
root $DOC_ROOT;vim
}
当用户利用nginx镜像启动为容器时,在容器内部的主进程启动以前先启动一个别的程序(程序A),这个程序(A)根据此镜像中的server.conf文件以及用户将镜像启动为容器时向容器传递的环境变量,把传递的变量替换在模板文件server.conf文件中,并保存。这里程序A先扮演主进程,是为后面真正的主进程预设环境的。而后程序A再启动主进程,程序A退出。由进程A启动程序B,而且程序B替换程序A,是使用exec命令进行操做。(启动一个子进程,可是子进程把当前启动它的进程替换掉并且子进程顶了当前进程的ID号)
云原生:Cloud Native Landscape
Docker可使用Dockerfile
文件来创建一个image镜像。 Dockerfile
中包含有创建image镜像的全部配置信息和可执行命令。 使用 docker build
命令就能够根据你指定的Dockerfile文件创建一个image镜像,Dockerfile配置决定了docker容器的运行状态和结构。
Dockerfile是一个包含用于组合映像的命令的文本文档。可使用在命令行中调用任何命令。 Docker经过读取Dockerfile
中的指令自动生成映像。
docker build
命令用于从Dockerfile构建映像。能够在docker build
命令中使用-f
标志指向文件系统中任何位置的Dockerfile。
Docker 镜像、容器和 Dockerfile 三者之间的关系
Dockerfile Format
Format:
指令自己不区分大小写,可是惯例是使用大写
Docker是按Dockerfile顺序执行指令(先后关系很重要);
第一个非注释行必须以 FROM 开头,表示当前镜像是以哪一个基础镜像构建。
Dockerfile的工做逻辑
一、基于dockerfile作docker镜像时,要找一个专用目录(即工做目录),在这个目录中放进dockerfile文件,dockerfile文件名首字母必须大写,
二、若是想利用dockerfile向镜像内打包进不少文件,须要提早准备好这些文件,而且把这些文件放在这个专用的目录中;
即基于dockerfile作镜像时所引用的文件的路径必须起始于这个专用目录以及其子目录;
能够把全部文件放在一个目录中,把这个目录放到专用目录中,这样能够在dockerfile中直接引用这个目录。
三、有一种状况,好比专用目中的子目录中包含50个文件,dockerfile在引用这个子目录时,这个子目录中的20个文件当前是不须要的,
那么就能够在专用目录中建立一个隐藏文件:.dockerignore,它又是一个文本文件,在.dockerignore中能够写进不须要引用的文件路径
(包括.dockerignore文件自己的路径),一行是一个文件路径,但行是可使用通配符的。写在.dockerignore中的文件路径的文件,在打包进镜像时都不包含进去。
制做镜像方式有基于容器来制做,首先容器基于原有镜像启动,而后联合挂载,添加可写层,对于容器的全部写操做都放在了可写层上面了,而后基于这个已经改变的容器建立一个镜像就能够了。但在可写层上执行的全部操做都是要交互式的链接进容器执行命令完成的,这些命令都是容器支持的命令。
docker build基于dockerfile启动一个容器时,不用本身手动启动容器,可是docker build隐藏式的启动了一个容器,跟上述人工启动容器区别并不大。
所以在dockerfile中能够执行不少命令,但这些命令不是宿主机的命令,而是底层镜像所包含的命令。若是底层镜像没有某个命令,那么在dockerfile中也没法运行。
因此全部镜像的制做环境是底层镜像在启动为容器时所能提供的给咱们的环境。
Environment replacement
Dockerfile Instructions 重点参考: http://www.javashuo.com/article/p-xaajfgxj-du.html
FROM
FROM:指定基础镜像,必须为第一个命令 http://www.javashuo.com/article/p-xaajfgxj-du.html
格式: CMD ["executable","param1","param2"] (执行可执行文件,优先) CMD ["param1","param2"] (设置了ENTRYPOINT,则直接调用ENTRYPOINT添加参数) CMD command param1 param2 (执行shell内部命令) 示例: CMD echo "This is a test." | wc - CMD ["/usr/bin/wc","--help"] 注: CMD不一样于RUN,CMD用于指定在容器启动时所要执行的命令,而RUN用于指定镜像构建时所要执行的命令。
MAINTANIER
格式:
MAINTAINER <name>
示例:
MAINTAINER Jasper Xu
MAINTAINER sorex@163.com
MAINTAINER Jasper Xu <sorex@163.com>
LABEL 让用户为镜像指定各类各样的元数据(元数据是键值数据)
格式: LABEL <key>=<value> <key>=<value> <key>=<value> ... 示例: LABEL version="1.0" description="这是一个Web服务器" by="IT笔录" 注: 使用LABEL指定元数据时,一条LABEL指定能够指定一或多条元数据,指定多条元数据时不一样元数据之间经过空格分隔。推荐将全部的元数据经过一条LABEL指令指定,以避免生成过多的中间镜像。
COPY 将宿主机上的文件或目录打包进镜像文件中
示例
注意:index.html必需要和Dockerfile在同一个目录或者在与Dockerfile所在目录下的子目录中
# docker build -h
Flag shorthand -h has been deprecated, please use --help Usage: docker build [OPTIONS] PATH | URL | - //PATH必须是Dockerfile所在的专用目录 Build an image from a Dockerfile Options: --add-host list Add a custom host-to-IP mapping (host:ip) --build-arg list Set build-time variables --cache-from strings Images to consider as cache sources --cgroup-parent string Optional parent cgroup for the container --compress Compress the build context using gzip --cpu-period int Limit the CPU CFS (Completely Fair Scheduler) period --cpu-quota int Limit the CPU CFS (Completely Fair Scheduler) quota -c, --cpu-shares int CPU shares (relative weight) --cpuset-cpus string CPUs in which to allow execution (0-3, 0,1) --cpuset-mems string MEMs in which to allow execution (0-3, 0,1) --disable-content-trust Skip image verification (default true) -f, --file string Name of the Dockerfile (Default is 'PATH/Dockerfile') --force-rm Always remove intermediate containers --iidfile string Write the image ID to the file --isolation string Container isolation technology --label list Set metadata for an image -m, --memory bytes Memory limit --memory-swap bytes Swap limit equal to memory plus swap: '-1' to enable unlimited swap --network string Set the networking mode for the RUN instructions during build (default "default") --no-cache Do not use cache when building the image --platform string Set platform if server is multi-platform capable --pull Always attempt to pull a newer version of the image -q, --quiet Suppress the build output and print image ID on success --rm Remove intermediate containers after a successful build (default true) --security-opt strings Security options --shm-size bytes Size of /dev/shm --squash Squash newly built layers into a single new layer --stream Stream attaches to server to negotiate build context -t, --tag list Name and optionally a tag in the 'name:tag' format --target string Set the target build stage to build. --ulimit ulimit Ulimit options (default [])
node1@img1]# docker build -t tinyhttpd:v0.1-1 ./ //使用docker build基于Dockerfile作镜像,注意 ./ 是当前目录 img1
Sending build context to Docker daemon 3.072kB Step 1/3 : FROM busybox:latest //分析FROM指令,获取基础镜像 ---> d8233ab899d4 Step 2/3 : MAINTAINER "Abc <abc@abc.com>" //加上MAINTAINER ---> Running in 5c39877eef22 Removing intermediate container 5c39877eef22 ---> 93f297e3e2e5 Step 3/3 : COPY index.html /data/web/html/ //复制文件到目标镜像中 ---> 026022e873de Successfully built 026022e873de Successfully tagged tinyhttpd:v0.1-1
[root@node1 img1]# docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE tinyhttpd v0.1-1 026022e873de About an hour ago 1.2MB
@node1 ~]# docker run --name tinyweb1 --rm tinyhttpd:v0.1-1 cat /data/web/html/index.html //将镜像启动为容器,而后查看文件是存在,而后直接退出,命令一结束容器就被删除了
<h1> Busybox httpd server.</h1>
示例:复制一个目录到专用目录下,而后将此目录下的文件所有打包进目标镜像,并放在yum.repo.d目录下
在dockerfile中每一条指令都会生成一个镜像层,若是多个指令能够合成一条,必定要合成一条。
此处不是复制yum.repos.d目录自己,而是复制目录下的文件。
由于复制的是目录,因此要把目标目录名写出来:/etc/yum.repos.d/,最后一个"/"必定要加上,否则会把文件复制为名为yum.repos.d的文件,而不是目录。
[root@node1 img1]# docker build -t tinyhttpd:v0.1-2 ./ //打包成镜像
Sending build context to Docker daemon 35.84kB Step 1/4 : FROM busybox:latest ---> d8233ab899d4 Step 2/4 : MAINTAINER "Abc <abc@abc.com>" ---> Using cache ---> 93f297e3e2e5 Step 3/4 : COPY index.html /data/web/html/ ---> Using cache ---> 026022e873de Step 4/4 : COPY yum.repos.d /etc/yum.repos.d/ ---> 948f2959ddb4 Successfully built 948f2959ddb4 Successfully tagged tinyhttpd:v0.1-2
ADD 将本地文件添加到容器中,tar类型文件会自动解压(网络压缩资源不会被解压),能够访问网络资源,相似wget
格式: ADD <src>... <dest> ADD ["<src>",... "<dest>"] 用于支持包含空格的路径 示例: ADD hom* /mydir/ # 添加全部以"hom"开头的文件 ADD hom?.txt /mydir/ # ? 替代一个单字符,例如:"home.txt" ADD test relativeDir/ # 添加 "test" 到 `WORKDIR`/relativeDir/ ADD test /absoluteDir/ # 添加 "test" 到 /absoluteDir/
示例:在网页上下载一个tar文件利用ADD打包进镜像中
[root@node1 img1]# vim Dockerfile
1 # Description: test image 2 FROM busybox:latest 3 MAINTAINER "Abc <abc@abc.com>" 4 # LABEL maintainer="Abc <abc@abc.com>" 5 COPY index.html /data/web/html/ 6 COPY yum.repos.d /etc/yum.repos.d/ 7 ADD https://nginx.org/download/nginx-1.14.2.tar.gz /usr/local/src/
//这里只会下载nginx-1.14不会被展开,由于源文件是URL,若是源文件是本地,则tar文件会被展开。若是/usr/local/src/目录不存在,会直接被建立,但必需要以斜线结尾
文件没有被解压
将nginx下载到专用目录中作测试
[root@node1 img1]# vim Dockerfile
1 # Description: test image 2 FROM busybox:latest 3 MAINTAINER "Abc <abc@abc.com>" 4 # LABEL maintainer="Abc <abc@abc.com>" 5 COPY index.html /data/web/html/ 6 COPY yum.repos.d /etc/yum.repos.d/ 7 # ADD https://nginx.org/download/nginx-1.14.2.tar.gz /usr/local/src/ 8 ADD nginx-1.14.2.tar.gz /usr/local/src/ //至关于tar -x nginx-1.14.2.tar.gz -C /usr/local/src/
[root@node1 img1]# docker build -t tinyhttpd:v0.1-4 ./
Sending build context to Docker daemon 1.052MB Step 1/5 : FROM busybox:latest ---> d8233ab899d4 Step 2/5 : MAINTAINER "Abc <abc@abc.com>" ---> Using cache ---> 93f297e3e2e5 Step 3/5 : COPY index.html /data/web/html/ ---> Using cache ---> 026022e873de Step 4/5 : COPY yum.repos.d /etc/yum.repos.d/ ---> Using cache ---> 948f2959ddb4 Step 5/5 : ADD nginx-1.14.2.tar.gz /usr/local/src/ ---> ffd35e42c975 Successfully built ffd35e42c975 Successfully tagged tinyhttpd:v0.1-4
已经解压
WORKDIR 工做目录
格式: WORKDIR /path/to/workdir 示例: WORKDIR /a (这时工做目录为/a) WORKDIR b (这时工做目录为/a/b) WORKDIR c (这时工做目录为/a/b/c) 注: 经过WORKDIR设置工做目录后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT、ADD、COPY等命令都会在该目录下执行。在使用docker run运行容器时,能够经过-w参数覆盖构建时所设置的工做目录。
[root@node1 img1]# vim Dockerfile
1 # Description: test image 2 FROM busybox:latest 3 MAINTAINER "Abc <abc@abc.com>" 4 WORKDIR /usr/local/src/ // 指定工做目录 5 ADD nginx-1.14.2.tar.gz ./ // ./就引用工做目录
或者更换为
WORKDIR /usr/local/src/
ADD nginx-1.14.2.tar.gz ./src/
VOLUME 用于指定持久化目录(只能使用docker管理的卷即只能指定容器上的挂载点,而不能指定宿主机上的挂载路径)
格式: VOLUME ["/path/to/dir"] 示例: VOLUME ["/data"] VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2" 注: 一个卷能够存在于一个或多个容器的指定目录,该目录能够绕过联合文件系统,并具备如下功能: 一、卷能够容器间共享和重用 二、容器并不必定要和其它容器共享卷 三、修改卷后会当即生效 四、对卷的修改不会对镜像产生影响 五、卷会一直存在,直到没有任何容器在使用它
示例:建立一个MySQL存储卷 /data/mysql 与宿主机创建关联关系
[root@node1 img1]# vim Dockerfile
1 # Description: test image 2 FROM busybox:latest 3 MAINTAINER "Abc <abc@abc.com>" 4 # LABEL maintainer="Abc <abc@abc.com>" 5 COPY index.html /data/web/html/ 6 # ADD https://nginx.org/download/nginx-1.14.2.tar.gz /usr/local/src/ 7 WORKDIR /usr/local/src/ 8 9 ADD nginx-1.14.2.tar.gz ./ 10 11 VOLUME /data/mysql/ //指定为数据存放目录
[root@node1 img1]# docker build -t tinyhttpd:v0.1-5 ./
Sending build context to Docker daemon 1.052MB Step 1/6 : FROM busybox:latest ---> d8233ab899d4 Step 2/6 : MAINTAINER "Abc <abc@abc.com>" ---> Using cache ---> 93f297e3e2e5 Step 3/6 : COPY index.html /data/web/html/ ---> Using cache ---> 026022e873de Step 4/6 : WORKDIR /usr/local/src/ ---> Running in 109b8104bcce Removing intermediate container 109b8104bcce ---> ba695cf12c59 Step 5/6 : ADD nginx-1.14.2.tar.gz ./ ---> c3c9e70e6bca Step 6/6 : VOLUME /data/mysql/ ---> Running in 4f70234badf5 Removing intermediate container 4f70234badf5 ---> a4edf21d7f10 Successfully built a4edf21d7f10 Successfully tagged tinyhttpd:v0.1-5
# docker run --name tinyweb1 --rm tinyhttpd:v0.1-5 mount | grep /data/mysql //验证
/dev/mapper/centos-root on /data/mysql type xfs (rw,relatime,attr2,inode64,noquota)
另一种方法是启动容器,而后让此容器睡眠60秒进行查看
[root@node1 ~]# docker run --name tinyweb1 --rm tinyhttpd:v0.1-5 sleep 60 //启动容器,睡眠60秒
[root@node1 ~]# docker inspect tinyweb1 //打开另一个窗口进行查看
EXPOSE 指定于外界交互的端口
只能指定暴露哪一个端口,是动态绑定的,由于是没有办法指定绑定在宿主机上的指定IP+端口,由于镜像启动为容器时,并不肯定在哪一个宿主机上启动,同时更没法肯定宿主机上的IP和空闲的端口。
所以只能指定容器启动时暴露出来的端口,而后去动态绑定只宿主机上的随机端口和全部地址。
格式: EXPOSE <port> [<port>...] 示例: EXPOSE 80 443 EXPOSE 8080 EXPOSE 11211/tcp 11211/udp 注: EXPOSE并不会让容器的端口访问到主机。要使其可访问,须要在 docker run 运行容器时经过 -p 来发布这些端口,或经过 -P(publishall) 参数来发布EXPOSE导出的全部端口
示例:
[root@node1 img1]# vim Dockerfile
1 # Description: test image 2 FROM busybox:latest 3 MAINTAINER "Abc <abc@abc.com>" 4 # LABEL maintainer="Abc <abc@abc.com>" 5 COPY index.html /data/web/html/ 6 # ADD https://nginx.org/download/nginx-1.14.2.tar.gz /usr/local/src/ 7 WORKDIR /usr/local/src/ 8 9 ADD nginx-1.14.2.tar.gz ./ 10 11 VOLUME /data/mysql/ 12 13 EXPOSE 80/tcp //指明容器的暴漏端口,但对外部网络并不必定是80端口,对外部显示的端口是此端口绑定在宿主机上的端口。若是只在Dockerfile中添加此命令,而启动容器是没有添加 -P,那么启动的容器依然不会暴漏端口的。
[root@node1 img1]# docker build -t tinyhttpd:v0.1-6 ./ //基于dockerfile打包镜像
[root@node1 ~]# docker run --name tinyweb1 --rm tinyhttpd:v0.1-6 /bin/httpd -f -h /data/web/html //直接启动httpd服务,-h 指定家目录,这里运行的是服务提供的web程序,-f 表示运行在前台
[root@node1 ~]# docker inspect tinyweb1 //查看IP
[root@node1 ~]# curl 10.0.0.2 //服务正常相应
<h1> Busybox httpd server.</h1>
[root@node1 ~]# docker port tinyweb1 //查看可知没有暴漏端口
[root@node1 ~]# docker kill tinyweb1 //删除此容器
tinyweb1
[root@node1 ~]# docker run --name tinyweb1 -P --rm tinyhttpd:v0.1-6 /bin/httpd -f -h /data/web/html //使用-P暴露端口,但没有指定暴漏哪一个端口
[root@node1 ~]# docker port tinyweb1
80/tcp -> 0.0.0.0:32768
ENV 为镜像定义所需的环境变量
格式: ENV <key> <value> #<key>以后的全部内容均会被视为其<value>的组成部分,所以,一次只能设置一个变量 ENV <key>=<value> ... #能够设置多个变量,每一个变量为一个"<key>=<value>"的键值对,若是<key>中包含空格,可使用\来进行转义,也能够经过""来进行标示;另外,反斜线也能够用于续行 示例: ENV myName John Doe ENV myDog Rex The Dog ENV myCat=fluffy
[root@node1 img1]# vim Dockerfile
1 # Description: test image //第一种环境变量的赋值方法 2 FROM busybox:latest 3 ENV DOC_ROOT /data/web/html/ //变量通常是大写 4 COPY index.html ${DOC_ROOT:-/data/web/html} //引用环境变量,若是环境变量没有值,则用/data/web/html进行代替
1 # Description: test image 2 FROM busybox:latest 3 ENV DOC_ROOT=/data/web/html/ \ //注意末尾的续行符 \ 4 WEB_SERVER_PACKAGE="nginx-1.14.2" 5 COPY index.html ${DOC_ROOT:-/data/web/html} 6 WORKDIR /usr/local/ 7 ADD ${WEB_SERVER_PACKAGE}.tar.gz ./src/
[root@node1 img1]# docker build -t tinyhttpd:v0.1-7 ./
Sending build context to Docker daemon 1.052MB Step 1/7 : FROM busybox:latest ---> d8233ab899d4 Step 2/7 : ENV DOC_ROOT=/data/web/html/ WEB_SERVER_PACKAGE="nginx-1.14.2" ---> Running in edd73b80c40d Removing intermediate container edd73b80c40d ---> 9c8c911dd79a Step 3/7 : COPY index.html ${DOC_ROOT:-/data/web/html} ---> 93ecd3596616 Step 4/7 : WORKDIR /usr/local/ ---> Running in 3ac341a77316 Removing intermediate container 3ac341a77316 ---> 26cfbd77b7eb Step 5/7 : ADD ${WEB_SERVER_PACKAGE}.tar.gz ./src/ ---> 4fbaf33a8955 Step 6/7 : VOLUME /data/mysql/ ---> Running in a6d4510a4313 Removing intermediate container a6d4510a4313 ---> efc1e5580ffc Step 7/7 : EXPOSE 80/tcp ---> Running in fc17649839d2 Removing intermediate container fc17649839d2 ---> 31c87ab706ef Successfully built 31c87ab706ef Successfully tagged tinyhttpd:v0.1-7
向变量传值
[root@node1 ~]# docker run --help
-e, --env list Set environment variables //设定变量值 --env-file list Read in a file of environment variables --expose list Expose a port or a range of ports --group-add list Add additional groups to join --health-cmd string Command to run to check health --health-interval duration Time between running the check (ms|s|m|h) (default 0s) --health-retries int Consecutive failures needed to report unhealthy --health-start-period duration Start period for the container to initialize before starting health-retries countdown (ms|s|m|h) (default 0s) --health-timeout duration Maximum time to allow one check to run (ms|s|m|h) (default 0s) --help Print usage
[root@node1 ~]# docker run --name tinyweb1 -P --rm tinyhttpd:v0.1-7 printenv //输出环境变量信息,在Dockerfile中定义的全部环境变量是能够在启动容器时直接在容器中引用的变量。
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=4e6dbb46ccbc
DOC_ROOT=/data/web/html/
WEB_SERVER_PACKAGE=nginx-1.14.2
HOME=/root
# docker run --name tinyweb1 -P -e WEB_SERVER_PACKAGE="nginx-1.15.1" --rm tinyhttpd:v0.1-7 printenv //此处在命令行中将镜像初始化为容器时向环境变量复制
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=36c490d420de
WEB_SERVER_PACKAGE=nginx-1.15.1
DOC_ROOT=/data/web/html/
HOME=/root
[root@node1 ~]# docker run --name tinyweb1 -P -e WEB_SERVER_PACKAGE="nginx-1.15.1" --rm tinyhttpd:v0.1-7 ls /usr/local/src //可是/usr/local/src/目录下的内容是不会变化的
nginx-1.14.2
上述结果中WEB_SERVER_PACKAGE=nginx-1.14.2写在了Dockerfile中,是在docker build阶段执行的,已经写进了镜像;
而 -e WEB_SERVER_PACKAGE="nginx-1.15.1" 是在 docker run 阶段执行的,是基于打包好的镜像启动为容器阶段;
因此此处修改环境变量只能显示环境变量的值发生改变,可是并不能真正改变docker build的结果,也没法对容器的程序配置有效果。
RUN和CMD的区别
CMD:把一个镜像启动为容器时要运行的命令(即上面ls /usr/local/src),若是不指定运行的命令,就有CMD来定义。CMD是定义把镜像启动为容器时在没有指定所要运行的命令状况下,默认要运行的命令。
RUN:当基于Dockerfile构建镜像时要运行的命令,将在docker build运行的命令叫RUN。
CMD是定义一个镜像文件启动为容器时默认要运行的程序,docker容器默认只运行一个程序,因此CMD只能一个(当CMD有多个时,只能最后一个生效)。但RUN 能够有多个,RUN命令时逐一运行的。
除了init以外,每个进程都应该是其余进程的子进程(init是内核启动的),当手动启动nginx时,那么这个nginx就以shell子进程存在。当打开一个命令行提示符时,这个就至关于在运行一个shell进程,当在shell命令行中运行一个命令时,就至关于运行一个shell子进程。
在一个docker容器运行一个程序或者应用,这个进程直接有内核建立启动仍是由shell启动?PID为1的进程应该由内核启动,由内核启动的进程有不少不便,由于这个进程不能使用shell进程下的一些功能(好比重定向、输入输出等功能)。若是在容器中基于shell启动一个进程,则这个进程的PID再也不为1,由于在启动进程以前要先启动shell进程,因此shell的PID是1。可是这种状况下shell是不能退出的,若是shell退出,它的子进程就挂掉了。此时可使用#exec COMMAND顶替COMMAND,取代shell进程,shell退出,shell的子进程PID就成了1。
在容器中启动进程时,能够不基于shell直接启动进程。若是要基于shell启动主进程,那就必需要这个主进程的PID为1,就能够经过 #exec COMMAND。
RUN
RUN用于在镜像容器中执行命令,其有如下两种命令执行方式: shell执行 格式: RUN <command> exec执行 格式: RUN ["executable", "param1", "param2"] 示例: RUN ["executable", "param1", "param2"] RUN apk update RUN ["/etc/execfile", "arg1", "arg1"] 注: RUN指令建立的中间镜像会被缓存,并会在下次构建中使用。若是不想使用这些缓存镜像,能够在构建时指定--no-cache参数,如:docker build --no-cache
RUN能够运行屡次,另外若是RUN有多条命令,建议把多条命令一次性写进来;
RUM COMMAND1 && \ //使用&&的好处在于若是第一个命令错误,那么就会中止下来,不会再执行第二个命令。
COMMAND2
CMD
格式: CMD ["executable","param1","param2"] (执行可执行文件,优先) CMD ["param1","param2"] (设置了ENTRYPOINT,则直接调用ENTRYPOINT添加参数) CMD command param1 param2 (执行shell内部命令) 示例: CMD echo "This is a test." | wc - CMD ["/usr/bin/wc","--help"] 注: CMD不一样于RUN,CMD用于指定在容器启动时所要执行的命令,而RUN用于指定镜像构建时所要执行的命令。
好比在Dockerfile中ADD一个URL,因为URL被打包进镜像时不会被自动展开,因此能够在docker build阶段使用RUN命令对此tar包进行解压。
但前提时基础镜像中要支持tar命令,在docker build阶段运行全部命令都是基于基础镜像所提供的环境的。
[root@node1 img1]# vim Dockerfile
1 # Description: test image 2 FROM busybox:latest 3 ENV DOC_ROOT=/data/web/html/ \ 4 WEB_SERVER_PACKAGE="nginx-1.14.2.tar.gz" 5 COPY index.html ${DOC_ROOT:-/data/web/html} 6 ADD https://nginx.org/download/${WEB_SERVER_PACKAGE} /usr/local/src/ 7 8 WORKDIR /usr/local/ 9 #ADD ${WEB_SERVER_PACKAGE}.tar.gz ./src/ 10 11 VOLUME /data/mysql/ 12 13 EXPOSE 80/tcp 14 15 RUN cd /usr/local/src && \ //能够运行多个命令 16 tar -xf ${WEB_SERVER_PACKAGE}
[root@node1 img1]# docker build -t tinyhttpd:v0.1-10 ./
Sending build context to Docker daemon 1.052MB Step 1/8 : FROM busybox:latest ---> d8233ab899d4 Step 2/8 : ENV DOC_ROOT=/data/web/html/ WEB_SERVER_PACKAGE="nginx-1.14.2.tar.gz" ---> Using cache ---> 2a3dd8ab77c5 Step 3/8 : COPY index.html ${DOC_ROOT:-/data/web/html} ---> Using cache ---> 7bcdbdd8dbdd Step 4/8 : ADD https://nginx.org/download/${WEB_SERVER_PACKAGE} /usr/local/src/ Downloading [==================================================>] 1.015MB/1.015MB ---> Using cache ---> 076581fd3385 Step 5/8 : WORKDIR /usr/local/ ---> Using cache ---> f1e1e3457cf7 Step 6/8 : VOLUME /data/mysql/ ---> Using cache ---> f901d29855d5 Step 7/8 : EXPOSE 80/tcp ---> Using cache ---> da0f851edb51 Step 8/8 : RUN cd /usr/local/src/ && tar xf ${WEB_SERVER_PACKAGE} ---> Running in b42a22ddc96c Removing intermediate container b42a22ddc96c ---> c0c7f3d670e2 Successfully built c0c7f3d670e2 Successfully tagged tinyhttpd:v0.1-10
# docker run --name tinyweb1 -P -e WEB_SERVER_PACKAGE="nginx-1.15.1" -it --rm tinyhttpd:v0.1-10 ls /usr/local/src //验证
nginx-1.14.2 nginx-1.14.2.tar.gz
[root@node1 ~]# mkdir img2
[root@node1 ~]# cd img2/
[root@node1 img2]# vim Dockerfile
1 FROM busybox
2 LABEL maintainer="hello <nihao@nihao.com>" app="httpd"
3
4 ENV=WEB_DOC_ROOT="/data/web/html/"
5 RUN mkdir -p $WEB_DOC_ROOT && \
6 echo '<h1>Busybox httpd server.</h1>' > ${WEB_DOC_ROOT}/index.html
7
8 CMD /bin/httpd -f -h ${WEB_DOC_ROOT} //这里定义默认运行的程序不是shell,而是httpd
[root@node1 img2]# docker build -t tinyhttpd:v0.3-2 ./ //制做镜像
[root@node1 img2]# docker image inspect tinyhttpd:v0.2-1 //查看镜像内容
执行交互式启动镜像,可是却卡在这里,由于httpd没有交互接口
(注意:若是容器tinyweb2不存在,就没法执行此操做。)
/bin/httpd进程的PID为1,这里为了不在启动tinyweb2容器时,/bin/httpd进程的PID为1,就使用了exec作了替换操做。
之因此让/bin/httpd主进程的PID为1,是为了确保此容器能够接受unix信号。