一、Dockerfile含义
Dockerfile 由一行行命令语句组成, 并且支持以#开头的注释行。一般而言, Dockerfile 主体内容分为四部分:基础镜像信息、 维护者信息、 镜像操作指令和容器启动时执行指令。
#1.Dockerfile是什么?
构建镜像所使用的指令配置文件
#2.Dockerfile基础部分
1、基础镜像,构建一个镜像所依赖的镜像(必须)
2、构建镜像的指令,按照我们需求自定义镜像
3、指定镜像启动命令,(指定容器启动的方式)
#3.使用Dockerfile需要注意的几点
1、dockerfile必须命名为`Dockerfile`
2、尽量将Dockerfile放在空目录中,如果目录中必须有其他文件,则使用.dockerignore文件。
3、避免安装不必须的包。
4、每个容器应该只关注一个功能点。
5、最小化镜像的层数。
6、多行参数时应该分类。这样更清晰直白,便于阅读和review,另外,在每个换行符\前都增加一个空格。
7、对构建缓存要有清楚的认识。
二、Dockerfile的使用
#1.格式:
docker build [参数] [dockerfile的路径]
#2.原理
在构建docker镜像的时候,实际上将当前目录移动到了一个虚拟目录当中,所有的操作路径都是以虚拟路径为准。
#3.参数:
-c : 指定使用CPU大小
-f : 指定dockerfile路径
-t : 指定构建后的镜像名称
三、Dockerfile文件说明
Docker以从上到下的顺序运行Dockerfile的指令。为了指定基本映像,第一条指令必须是FROM。一个声明以#字符开头则被视为注释。可以在Docker文件中使用RUN,CMD,FROM,EXPOSE,ENV等指令。
1、FROM指令:指定基础镜像,必须为第一个命令
#1.解释:
指定构建镜像的基础镜像(有且只能有一个基础镜像)
#2.格式:
FROM [基础镜像]:[镜像版本号]
FROM <image>
FROM <image>:<tag>
FROM <image>@<digest>
#3.示例:
FROM mysql:5.6
#4.注:
tag或digest是可选的,如果不使用这两个值时,会使用latest版本的基础镜像
2、MAINTAINER指令:维护者信息
#1.解释:
指定维护者信息(现在已经淘汰)
#2.格式:
MAINTAINER [名字] [des] [...]
MAINTAINER <name>
#3.示例:
MAINTAINER Jasper Xu
MAINTAINER sorex@163.com
MAINTAINER Jasper Xu <sorex@163.com>
3、RUN指令:构建镜像时执行的命令
#1.解释:
RUN用于在镜像容器中执行命令,其有以下两种命令执行方式:
#2.执行方式:
1.shell执行
格式:
RUN [linux命令]
RUN <command>
2.exec执行
格式:
RUN ["executable", "param1", "param2"]
#3.示例:
RUN ["executable", "param1", "param2"]
RUN apk update
RUN ["/etc/execfile", "arg1", "arg1"]
#4.注:
RUN指令创建的中间镜像会被缓存,并会在下次构建中使用。如果不想使用这些缓存镜像,可以在构建时指定--no-cache参数,如:docker build --no-cache
4、ADD指令:将本地文件添加到容器中
#1.解释:
将本地文件添加到容器中,添加文件到镜像中,ADD指令有一个自动解压的功能(tar),ADD指令可以下载互联网上的文件但是不解压。
#2.格式:
ADD [宿主主机文件路径(必须使用相对路径)] [添加到镜像中的文件路径]
ADD <src>... <dest>
ADD ["<src>",... "<dest>"] 用于支持包含空格的路径
#3.示例:
ADD hom* /mydir/ # 添加所有以"hom"开头的文件
ADD hom?.txt /mydir/ # ? 替代一个单字符,例如:"home.txt"
ADD test relativeDir/ # 添加 "test" 到 `WORKDIR`/relativeDir/
ADD test /absoluteDir/ # 添加 "test" 到 /absoluteDir/
# 添加文件到容器当中
ADD ./1.txt /root
# 添加一个压缩包,测试是否会自动解压
ADD etcd-v3.0.17-darwin-amd64.zip /opt
# 在网上下载文件至镜像中(不会自动解压)
ADD https://mirrors.huaweicloud.com/etcd/v3.0.17/v3.0.17.tar.gz /opt
# 测试正则
ADD etcd-v3.0.17* /tmp/
# 测试ADD文件
ADD mysql.txt /root/
#4.注:
ADD指令支持正则(路径必须以/结尾)
5、COPY指令 :功能类似ADD,但是是不会自动解压文件,也不能访问网络资源
#1.解释:
复制一个文件到镜像中
#2.格式:
COPY [宿主主机文件路径(必须使用相对路径,只能向下找文件)] [添加到镜像中的文件路径]
COPY < src>… < dest>|[“< src>”,… “< dest>”]
#3.示例:
# 测试COPY正则
COPY etcd-v3.0.17* /etc/
# 测试COPY文件
COPY mysql.txt /opt/
# 测试COPY
COPY ./1.txt /opt
# 测试COPY解压功能
COPY etcd-v3.0.17-linux-amd64.tar.gz /opt
#4.注:
COPY指令没有解压功能.
COPY指令不支持互联网下载.
COPY指令支持正则.
ps:指令逻辑和ADD十分相似,同样Docker Daemon会从编译目录寻找文件或目录,dest为镜像中的绝对路径或者相对于WORKDIR的路径
6、CMD指令: 构建容器后调用,也就是在容器启动时才进行调用
#1.解释:
指定容器启动时默认命令
#2.格式:
CMD ["executable","param1","param2"] (执行可执行文件,优先)
CMD ["param1","param2"] (设置了ENTRYPOINT,则直接调用ENTRYPOINT添加参数)
CMD command param1 param2 (执行shell内部命令)
#3.示例:
CMD echo "This is a test." | wc -
CMD ["/usr/bin/wc","--help"]
CMD /bin/bash
CMD ["nginx","-g","daemon off;"]
#4. 注:
CMD不同于RUN,CMD用于指定在容器启动时所要执行的命令,而RUN用于指定镜像构建时所要执行的命令。
7、LABEL指令:用于为镜像添加元数据
#1.解释:
使用LABEL指定元数据时
#2.格式:
LABEL <key>=<value> <key>=<value> <key>=<value> ...
#3.示例:
LABEL version="1.0" description="这是一个Web服务器" by="IT笔录"
LABEL key=value
#4.注:
使用LABEL指定元数据时,一条LABEL指定可以指定一或多条元数据,指定多条元数据时不同元数据之间通过空格分隔。推荐将所有的元数据通过一条LABEL指令指定,以免生成过多的中间镜像。
8、ENV指令:设置环境变量
#1.解释:
指定环境变量
#2.格式:
ENV <key> <value> #<key>之后的所有内容均会被视为其<value>的组成部分,因此,一次只能设置一个变量
ENV <key>=<value> ... #可以设置多个变量,每个变量为一个"<key>=<value>"的键值对,如果<key>中包含空格,可以使用\来进行转义,也可以通过""来进行标示;另外,反斜线也可以用于续行
#3.示例:
ENV myName John Doe
ENV myDog Rex The Dog
ENV myCat=fluffy
ENV NGINX_WORKER=5
[root@docker ~/docker/nginx]# docker exec wizardly_cannon printenv
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
NGINX_WORKER=5
ENV NGINX_DES nginx server is very 666
[root@docker ~/docker/nginx]# docker exec amazing_driscoll printenv
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
NGINX_DES=nginx server is very 666
#4.查看环境变量
[root@m01 ~]# docker exec {containerID} env
9、EXPOSE指令:指定于外界交互的端口
#1.解释:
指定向外暴露的端口
#2.格式:
EXPOSE <port> [<port>...]
#3.示例:
EXPOSE 80 443
EXPOSE 8080
EXPOSE 11211/tcp 11211/udp
EXPOSE 80 443 1000 10000
[root@docker ~/docker/nginx]# docker run -d test/nginx:v12
e4f0b3a673dd9c83d2ecdb40c1726d3bed595890eeb9eab7fefb3218eb5650dc
[root@docker ~/docker/nginx]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e4f0b3a673dd test/nginx:v12 "/docker-entrypoint.…" 3 seconds ago Up 3 seconds 80/tcp, 443/tcp, 1000/tcp, 10000/tcp naughty_fermat
EXPOSE 80 443 1000/udp 10000
[root@docker ~/docker/nginx]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e1e4f2c18f40 test/nginx:v13 "/docker-entrypoint.…" 48 seconds ago Up 48 seconds 80/tcp, 443/tcp, 10000/tcp, 1000/udp hungry_aryabhata
#4.注:
EXPOSE并不会让容器的端口访问到主机。要使其可访问,需要在docker run运行容器时通过-p来发布这些端口,或通过-P参数来发布EXPOSE导出的所有端口
10、VILUME指令: 用于指定持久化目录
#1.解释:指定挂载点
#2.格式:
VOLUME ["/path/to/dir"]
#3.示例:
VOLUME ["/data"]
VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"]
VOLUME /data
docker inspect test/nginx:v14
"Mounts": [
{
"Type": "volume",
"Name": "b9b87662e3296ea94db87b48ef642933751f53fe7bf715026f59043bc65335f0",
"Source": "/var/lib/docker/volumes/b9b87662e3296ea94db87b48ef642933751f53fe7bf715026f59043bc65335f0/_data",
"Destination": "/data",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
#4.注:
一个卷可以存在于一个或多个容器的指定目录,该目录可以绕过联合文件系统,并具有以下功能:
1.卷可以容器间共享和重用
2.容器并不一定要和其它容器共享卷
3.修改卷后会立即生效
4.对卷的修改不会对镜像产生影响
5.卷会一直存在,直到没有任何容器在使用它
6.共享存储卷:docker run --valumes-from [共享容器的名称] [镜像名称]
docker run -d --volumes-from upbeat_mcclintock test/nginx:v16
7.如果使用-v参数,将挂载指定的目录,不使用则自动生成挂载。
11、ARG指令:1.1、 用于指定传递给构建运行时的变量
#1.解释:
设置运行时参数,一般是在构建时使用
#2.格式:
ARG key : 需要用到docker build --build-arg key=value
ARG key=value
ARG <name>[=<default value>]
#3.示例:
[root@docker ~/docker/nginx]# docker exec 7ed524e38ac8 cat log
value
ARG site
ARG build_user=www
12、ONBUILD指令:用于设置镜像触发器
#1.解释:
镜像触发器(当当前镜像作为基础镜像时,执行)
#2.格式:
ONBUILD [dockerfile指令]
ONBUILD [INSTRUCTION]
ONBUILD RUN touch 1.txt
#3.示例:
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
#4.注:
当所构建的镜像被用做其它镜像的基础镜像,该镜像中的触发器将会被钥触发
13. WORKDIR:工作目录,类似于cd命令
#1.格式:
WORKDIR /path/to/workdir
#2.示例:
WORKDIR /a (这时工作目录为/a)
WORKDIR b (这时工作目录为/a/b)
WORKDIR c (这时工作目录为/a/b/c)
#3.注:
通过WORKDIR设置工作目录后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT、ADD、COPY等命令都会在该目录下执行。在使用docker run运行容器时,可以通过-w参数覆盖构建时所设置的工作目录。
四、Dockerfile构建镜像案例一
1.新建Dockerfile
1.新建目录
[root@m01 ~]# mkdir /docker/
[root@m01 ~]# cd /docker
2.新建Dockerfile
[root@m01 /docker]# cat Dockerfile
#Is my first nginx Dockerfile
# Version 1.0
# Base images 基础镜像
FROM centos
#MAINTAINER 维护者信息
MAINTAINER jh
#ADD 文件放在当前目录下,拷过去会自动解压
ADD nginx-1.18.0.tar.gz /usr/local/
ADD epel-release-latest-7.noarch.rpm /usr/local/
#RUN 执行以下命令
RUN rpm -ivh /usr/local/epel-release-latest-7.noarch.rpm
RUN yum install -y gcc gcc-c++ autoconf pcre pcre-devel make automake wget httpd-tools vim tree && yum clean all
RUN useradd -s /sbin/nologin -M www
#WORKDIR 相当于cd
WORKDIR /usr/local/nginx-1.18.0
RUN ./configure --prefix=/usr/local/nginx --user=www --group=www --with-http_addition_module --with-http_auth_request_module --without-http_gzip_module && make && make install
RUN echo "daemon off;" >> /etc/nginx.conf
#ENV 设置环境变量
ENV PATH /usr/local/nginx/sbin:$PATH
#EXPOSE 映射端口
EXPOSE 80
#CMD 运行以下命令
CMD ["nginx"]
2.上传相关安装包
[root@m01 /docker]# rz
-rw-r--r-- 1 root root 918 Jan 14 20:59 Dockerfile
-rw-r--r-- 1 root root 15448 Jan 14 19:44 epel-release-latest-7.noarch.rpm
-rw-r--r-- 1 root root 1039530 Jan 14 19:44 nginx-1.18.0.tar.gz
3.创建镜像
[root@m01 /docker]# docker build -t centos_nginx:v4 .
[root@m01 /docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos_nginx v4 f87c2b493910 7 minutes ago 483MB
centos latest 300e315adb2f 5 weeks ago 209MB
4.备份镜像
[root@m01 /docker]# docker save f87c2b493910 > centos_nginx:v4.tar
5.运行容器
[root@m01 /docker]# docker run -d -p81:80 centos_nginx:v4 nginx -g "daemon off;"
535f5d0f2829c1d4642020f03e8d48616f31edfe111bab02173f0815892d3698
五、Dockerfile构建镜像案例二
1.新建Dockerfile
1.新建目录
[root@m01 ~]# mkdir /docker/
[root@m01 ~]# cd /docker
2.新建Dockerfile
[root@m01 /docker]# vim Dockerfile
#Is my first nginx Dockerfile
# Version 1.0
# Base images 基础镜像
FROM centos
#MAINTAINER 维护者信息
MAINTAINER Jin Hui
#ADD 下载相关文件放在当前目录下,不会自动解压
ADD http://nginx.org/download/nginx-1.18.0.tar.gz /usr/local/
ADD https://mirrors.aliyun.com/epel/epel-release-latest-8.noarch.rpm /usr/local/
#RUN 执行以下命令
RUN tar xf /usr/local/nginx-1.18.0.tar.gz -C /usr/local/
RUN rpm -ivh /usr/local/epel-release-latest-8.noarch.rpm
RUN yum -y install gcc gcc-c++ autoconf pcre pcre-devel make automake wget httpd-tools vim tree && yum clean all
RUN useradd -s /sbin/nologin -M www
#WORKDIR 相当于cd
WORKDIR /usr/local/nginx-1.18.0
#RUN 执行以下命令
RUN ./configure --prefix=/usr/local/nginx --user=www --group=www --with-http_addition_module --with-http_auth_request_module --without-http_gzip_module && make && make install
#ENV 设置环境变量
ENV PATH /usr/local/nginx/sbin:$PATH
#EXPOSE 映射端口
EXPOSE 80
#CMD 运行以下命令
CMD ["nginx","-g","daemon off;"]
2.构建镜像
[root@m01 /docker]# docker build --no-cache -t centos_nginx:v1 .
[root@m01 /docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos_nginx v1 ca2a0d26d619 21 minutes ago 521MB
centos latest 300e315adb2f 5 weeks ago 209MB
3.备份镜像
[root@m01 /docker]# docker save ca2a0d26d619 > centos_nginx:v1.tar
4.运行容器
[root@m01 /docker]# docker run -d -p 80:80 --name nginx centos_nginx:v1
dd014764a0d192cb6185d3db92e34a8e0358cf125c20d0a68a80b6a598e84c63
5.测试镜像
[root@docker100 ~/1]# curl 127.0.0.1:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>