前面的docker镜像管理章节有说到,构建镜像的方式有两种:
简要概括Dockerfile的作用:它可以让用户个性化定制Docker镜像。因为工作环境中的需求各式各样,网络上的镜像很难满足实际的需求。
Dockerfile 是一个文本格式的配置文件,用户可以使用 Dockerfile 快速创建自定义镜像。
Dockerfile 由一行行命令语句组成,并且支持以 # 开头的注释行。
Dockerfile整体就两类语句组成
Dockerfile中指令按顺序从上至下依次执行。
Dockerfile中第一个非注释行必须是FROM指令,用来指定制作当前镜像依据的是哪个基础镜像。
Dockerfile中需要调用的文件必须跟Dockerfile文件在同一目录下,或者在其子目录下,父目录或者其它路径无效。
指令的一般格式为INSTRUCTION arguments
,指令包括:
FROM #基础镜像,一切从这里开始构建
MAINTAINER #镜像是谁写的,姓名+邮箱
RUN #镜像构建的时候需要运行的命令
ADD #步骤,tomcat镜像,这个tomcat的压缩包!添加内容
WORKDIR #镜像的工作目录
VOLUME #挂载的目录
EXPOSE #暴露端口配置
CMD #指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT #指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD #当构建一个被继承 Dockerfile 这个时候就会运行ONBUILD 的指令
COPY #类似ADD,将我们文件拷贝到镜像中
ENV #构建的时候设置环境遍量
//示例
#第一行必须指定基于的基础镜像
FROM centos
#维护人的信息
LABEL MAINTAINER="CWT <[email protected]>"
#安装httpd软件包
RUN yum -y update && \
yum -y install httpd
#开启80端口
EXPOSE 80
#复制网站首页文件至镜像中web站点下
ADD index.html /var/www/html/index.html
#复制该脚本至镜像中,并修改其权限
ADD httpd.sh /httpd.sh
RUN chmod 775 /httpd.sh
#当启动容器时默认要执行的动作
CMD ["/httpd.sh"]
其中,一开始必须指明所基于的镜像名称,接下来一般会说明维护者信息。
后面则是镜像操作指令,例如RUN指令,RUN指令将对镜像执行跟随的命令。每运行一条RUN指令,镜像添加新的一层,并提交。
最后是CMD指令来指定运行容器时的操作指令。
第一条指令必须为FROM指令。并且,如果在同一个Dockerfile中创建多个镜像时,可以使用多个FROM指令(每个镜像一次)
//语法格式:FROM 或FROM :
//构建新镜像是基于那个镜像
FROM centos:7
指定维护者信息
//语法格式: MAINTAINER
LABEL MAINTAINER='[email protected]'
RUN指令将对镜像执行跟随的命令
//RUN指令的语法格式有两种:
shell格式:(默认用/bin/sh -c来执行)
RUN RUN <命令行命令>
# <命令行命令> 等同于,在终端操作的 shell 命令。
exec格式:
RUN ["executable","param1","param2"] RUN ["可执行文件", "参数1", "参数2"]
# 例如:
# RUN ["./test.php", "dev", "offline"] 等价于 RUN ./test.php dev offline
注意: 每运行一条RUN指令,镜像添加新的一层,并提交,所以过多无意义的层,会造成镜像膨胀过大。所以当命令较长时可以使用 \ 来换行
RUN echo "hello world\nhello tom" > /tmp/abc && \
cat /tmp/abc
//语法格式:
CMD ["executable","param1","param2"]使用exec执行,推荐方式
CMD command param1 param2在/bin/sh中执行,提供给需要交互的应用
CMD ["param1","param2"]提供给ENTRYPOINT的默认参数
例如:CMD ["nginx", "-g", "daemon off;"]
EXPOSE用于告诉Docker服务器容器暴露的端口号,供互联系统使用。
在启动容器时通过-P,Docker主机会自动分配一个端口转发到指定的端口,使用-p则可以具体指定哪个本地端口映射过来
//语法格式:EXPOSE [...]
例如:EXPOSE 80 443 22
指定一个环境变量,会被后续 RUN 指令使用,并在容器运行时保持
//语法格式:
ENV
ENV = =...
例如:
ENV NODE_VERSION 7.2.0
RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" \
&& curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc"
//语法格式:
COPY [--chown=:] ...
COPY [--chown=:] ["",... ""]
[--chown=:]:可选参数,用户改变复制到容器内文件的拥有者和属组。
<源路径>:源文件或者源目录,这里可以是通配符表达式,其通配符规则要满足 Go 的 filepath.Match 规则。例如:
COPY hom* /mydir/
COPY hom?.txt /mydir/
该命令将复制指定的到容器中的。其中可以是Dockerfile所在目录的一个相对路径(文件或目录);也可以是一个URL;还可以是一个tar文件(会自动解压为目录)
ADD 指令和 COPY 的使用格式一致(同样需求下,官方推荐使用 COPY)。功能也类似,不同之处如下
如果src是目录,只复制目录中的内容,而非目录本身
如果src是一个 URL ,下载后的文件权限自动设置为 600
//语法格式:
ADD [--chown=:] ...
ADD [--chown=:] ["",... ""]
例如:
ADD test /absoluteDir/
ADD --chown=55:mygroup files* /somedir/
ADD --chown=bin files* /somedir/
ADD --chown=1 files* /somedir/
ADD --chown=10:11 files* /somedir/
ADD ubuntu-xenial-core-cloudimg-amd64-root.tar.gz
//语法格式:
ENTRYPOINT ["executable","param1","param2"]
ENTRYPOINT command param1 param2(在shell中执行)
例如:
FROM nginx
ENTRYPOINT ["nginx", "-c"] # 定参
CMD ["/etc/nginx/nginx.conf"] # 变参
运行容器:docker run nginx:test #没有传参
容器内会默认运行以下命令,启动主进程。
nginx -c /etc/nginx/nginx.conf
docker run nginx:test -c /etc/nginx/new.conf #传参
容器内会默认运行以下命令
nginx -c /etc/nginx/new.conf
创建一个可以从本地主机或其他容器挂载的挂载点,一般用来存放数据库和需要保持的数据等
//语法格式:
VOLUME ["<容器内路径1>", "<容器内路径2>"...]
VOLUME <路径>
//例如
VOLUME /data
//语法格式:
USER [:]
USER [:]
例如:
RUN groupadd -r mysql && useradd -r -g mysql mysql
USER mysql
指定工作目录。用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在。(WORKDIR 指定的工作目录,必须是提前创建好的)。
docker build 构建镜像过程中的,每一个 RUN 命令都是新建的一层。只有通过 WORKDIR 创建的目录才会一直存在。
可以使用多个WORKDIR指令,后续命令如果参数是相对路径,则会基于之前命令指定的路径。
//语法格式:
WORKDIR <工作目录路径>
例如:
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
最终路径为/a/b/c
用于延迟构建命令的执行。简单的说,就是 Dockerfile 里用 ONBUILD 指定的命令,在本次构建镜像的过程中不会执行(假设镜像为 test-build)。当有新的 Dockerfile 使用了之前构建的镜像 FROM test-build ,这是执行新镜像的 Dockerfile 构建时候,会执行 test-build 的 Dockerfile 里的 ONBUILD 指定的命令。
//语法格式:ONBUILD [INSTRUCTION]
例如,Dockerfile使用如下的内容创建了镜像test-build
[...]
ONBUILD ADD nginx.conf /usr/local/nignx/nginx.conf
ONBUILD RUN mkdir /data
[...]
此时,如果基于test-build创建新的镜像时,新的Dockerfile中使用FROM test-build指定基础镜像时,会自动执行ONBUILD指令的内容,等价于在后面添加了两条指令。
FROM test-build
# Automatically run the following
ADD nginx.conf /usr/local/nignx/nginx.conf
RUN mkdir /data
编写完成Dockerfile后,可以通过docker build命令来创建镜像。
基本的格式为docker build [选项] 路径,该命令将读取指定路径下(包括子目录)的Dockerfile,并将该路径下所有内容发送给Docker服务端,由服务端来创建镜像。因此一般建议放置Dockerfile的目录为空目录。
另外,可以通过 .dockerignore 文件(每一行添加一条匹配模式)来让Docker忽略路径下的目录和文件。
要指定镜像的标签信息,可以通过-t选项。
例如,指定Dockerfile所在路径为/tmp/docker_builder/,并且希望生成镜像标签为build_repo/first_image,可以使用下面的命令
docker build -t build_repo/first_image /tmp/docker_builder/
//创建目录
[root@docker ~]# ls
anaconda-ks.cfg
[root@docker ~]# mkdir /apache
[root@Docker ~]# cd /apache/
[root@Docker apache]# touch Dockerfile
[root@Docker apache]# ls
Dockerfile
[root@Docker apache]# mkdir packages
[root@Docker apache]# cd packages/
[root@Docker packages]# mv /usr/src/apr-1.7.0.tar.gz .
[root@Docker packages]# mv /usr/src/apr-util-1.6.1.tar.gz .
[root@Docker packages]# mv /usr/src/httpd-2.4.48.tar.gz .
[root@Docker ~]# tree
.
├── anaconda-ks.cfg
└── apache
├── Dockerfile
└── packages
├── apr-1.7.0.tar.gz
├── apr-util-1.6.1.tar.gz
└── httpd-2.4.48.tar.gz
/编写dockerfile
[root@Docker ~]# cat apache/Dockerfile
[root@docker apache]# cat Dockerfile
# 第一行必须指定基于的基础镜像
FROM centos
# 维护者信息
LABEL MAINIAINER='[email protected]'
# 将源码包传到指定文件,并会自动解压
ADD packages/* /usr/src/
# 切换到当前所在目录
WORKDIR /usr/src/
# 镜像操作指令
# 下载所需的安装包
RUN yum -y install openssl-devel pcre-devel pcre expat-devel libtool gcc gcc-c++ make && \
# 编译安装apr
cd apr-1.7.0 && sed -i '/$RM "$cfgfile"/d' configure && \
./configure --prefix=/usr/local/apr && make && make install && \
# 编译安装apr-util
cd ../apr-util-1.6.1 && \
./configure --prefix=/usr/local/apr-util --with-apr=/usr/local/apr && \
make && make install && \
# 编译安装httpd
cd ../httpd-2.4.48 && \
./configure --prefix=/usr/local/apache \
--enable-so \
--enable-ssl \
--enable-cgi \
--enable-rewrite \
--with-zlib \
--with-pcre \
--with-apr=/usr/local/apr \
--with-apr-util=/usr/local/apr-util/ \
--enable-modules=most \
--enable-mpms-shared=all \
--with-mpm=prefork && \
make && make install
sed -i '/#ServerName/s/#//g' /usr/local/apache/conf/httpd.conf
#设置存储卷
VOLUME ["/usr/local/apache/htdocs/"]
#启动命令
CMD ["/usr/local/apache/bin/apachectl","-D","FOREGROUND"]
//创建镜像
[root@Docker ~]# docker build -t caiaoc/apache:v1.0 /apache/
[root@docker apache]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
caiaoc/apache v1.0 b1386d62fb74 2 hours ago 701MB
nginx latest f652ca386ed1 5 days ago 141MB
busybox latest d23834f29b38 7 days ago 1.24MB
httpd latest ad17c88403e2 2 weeks ago 143MB
centos latest 5d0da3dc9764 2 months ago 231MB
//使用刚刚创建的镜像启动容器,开放端口,创建容器
[root@docker apache]# docker run --name apache1 -itd -p 80:80 caiaoc/apache:v1.0
7e6e7a2bc6b460eba55d55a61acdf89ac8d9e316ffa73ca0e541fddf378d9791
[root@docker apache]# docker exec -it apache1 /bin/bash
[root@7e6e7a2bc6b4 src]# ss -antl
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 128 0.0.0.0:80 0.0.0.0:*