dockerfile介绍
Dockerfile是由一系列命令和参数构成的脚本,一个Dockerfile里面包含了构建整个image的完整命令。Docker通过docker build执行Dockerfile中的一系列命令自动构建image。
docker脚本结构
Dockerfile 一般分为四部分:
- 基础镜像信息
- 维护者信息
- 镜像操作指令
- 容器启动时执行指令
常用指令
FROM:指定基础镜像,必须为第一个命令
- 语法
FROM <image>
FROM <image>:<tag>
FROM <image>@<digest>
- 示例
from mysql:v5.6
LABEL:为镜像生成元数据标签信息
- 语法
LABEL <key>=<value> <key>=<value> <key>=<value> ...
MAINTAINER:维护者信息
- 语法
MAINTAINER <name>
RUN:构建镜像时执行的命令
- 语法
- shell执行(默认调用/bin/sh)
RUN <command>
- exec执行(将会调用exec执行,以避免有些时候shell方式执行时的传递参数问题,而且有些基础镜像可能不包含/bin/sh)
RUN ["executable", "param1", "param2"]
注意:RUN指令创建的中间镜像会被缓存,并会在下次构建中使用。如果不想使用这些缓存镜像,可以在构建时指定--no-cache参数,如:docker build --no-cache
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/
COPY
- 功能类似ADD,但是不会自动解压文件,也不能访问网络资源
CMD
- 构建容器后调用,也就是在容器启动时才进行调用
- 语法:
CMD ["executable","param1","param2"] (执行可执行文件,优先)
CMD ["param1","param2"] (设置了ENTRYPOINT,则直接调用ENTRYPOINT添加参数)
CMD command param1 param2 (执行shell内部命令)
- 实例:
CMD echo "This is a test."
CMD ["/usr/bin/wc","--help"]
注意:CMD不同于RUN,CMD用于指定在容器启动时所要执行的命令,而RUN用于指定镜像构建时所要执行的命令
ENTRYPOINT
- 配置容器,使其可执行化。配合CMD可省去"application",只使用参数。
- 语法:
ENTRYPOINT ["executable", "param1", "param2"] (可执行文件, 优先)
ENTRYPOINT command param1 param2 (shell内部命令)
- 实例:
FROM ubuntu
ENTRYPOINT ["top", "-b"]
CMD ["-c"]
注意:ENTRYPOINT与CMD非常类似,不同的是通过docker run执行的命令不会覆盖ENTRYPOINT,而docker run命令中指定的任何参数,都会被当做参数再次传递给ENTRYPOINT。Dockerfile中只允许有一个ENTRYPOINT命令,多指定时会覆盖前面的设置,而只执行最后的ENTRYPOINT指令。
ENV
- 设置环境变量
- 语法:
ENV <key> <value> #<key>之后的所有内容均会被视为其<value>的组成部分,因此,一次只能设置一个变量
ENV <key>=<value> ...#可以设置多个变量,每个变量为一个"<key>=<value>"的键值对
- 实例:
ENV myName John Doe
ENV myDog Rex The Dog
ENV myCat=fluffy
EXPOSE
- 指定于外界交互的端口
- 语法:
EXPOSE <port> [<port>...]
- 实例:
EXPOSE 80 443
EXPOSE 8080
EXPOSE 11211/tcp 11211/udp
VOLUME
- 用于指定持久化目录
- 语法:
VOLUME ["/path/to/dir"]
- 实例:
VOLUME ["/data"]
VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"]
WORKDIR
- 工作目录,类似于cd命令
- 语法:
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参数覆盖构建时所设置的工作目录。
USER
- 指定运行容器时的用户名或 UID,后续的 RUN 也会使用指定用户。使用USER指定用户时,可以使用用户名、UID或GID,或是两者的组合。当服务不需要管理员权限时,可以通过该命令指定运行用户。并且可以在之前创建所需要的用户
- 语法:
USER user
USER user:group
USER uid
USER uid:gid
USER user:gid
USER uid:group
注意:使用USER指定用户后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT都将使用该用户。镜像构建完成后,通过docker run运行容器时,可以通过-u参数来覆盖所指定的用户
ONBUILD
- 用于设置镜像触发器
- 语法:
ONBUILD [INSTRUCTION]
- 实例:
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
注意:当所构建的镜像被用做其它镜像的基础镜像,该镜像中的触发器将会被触发
常见指令图示
利用dockerfile创建nginx容器
- 下载基础镜像(这里以alpine系统为base image)
[root@localhost ~]# docker pull alpine
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
busybox latest a77dce18d0ec 12 days ago 1.24MB
alpine latest 389fef711851 3 weeks ago 5.58MB
httpd latest dd85cdbb9987 4 weeks ago 138MB
nginx stable 05f64a802c26 4 weeks ago 133MB
ubuntu latest f643c72bc252 6 weeks ago 72.9MB
- 编写dockerfile文件
[root@localhost ~]# mkdir dock_Files
[root@localhost ~]# cd dock_Files/
[root@localhost dock_Files]# vim dockerfile
# 选择基础源
from alpine
# 基础元信息
label maintainer='sawyer 121692881@qq.com'
# 镜像操作
run sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories &&
apk update && apk add nginx
run mkdir -p /run/nginx &&
echo -e "
daemon off;" >> /etc/nginx/nginx.conf
# 默认进程
cmd ["nginx"]
- 创建镜像
[root@localhost dock_Files]# docker build -t nginx:test01 dock_Files/
Sending build context to Docker daemon 2.048kB
Step 1/5 : from alpine
---> 389fef711851
Step 2/5 : label maintainer='sawyer 121692881@qq.com'
---> Using cache
---> f8d805c6fe46
Step 3/5 : run sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories && apk update && apk add nginx
---> Running in ef7369fac685
fetch http://mirrors.aliyun.com/alpine/v3.12/main/x86_64/APKINDEX.tar.gz
fetch http://mirrors.aliyun.com/alpine/v3.12/community/x86_64/APKINDEX.tar.gz
v3.12.3-47-g3428e040de [http://mirrors.aliyun.com/alpine/v3.12/main]
v3.12.3-48-gea3fd89439 [http://mirrors.aliyun.com/alpine/v3.12/community]
OK: 12746 distinct packages available
(1/2) Installing pcre (8.44-r0)
(2/2) Installing nginx (1.18.0-r1)
Executing nginx-1.18.0-r1.pre-install
Executing busybox-1.31.1-r19.trigger
OK: 7 MiB in 16 packages
Removing intermediate container ef7369fac685
---> 7eb3e1570523
Step 4/5 : run mkdir -p /run/nginx && echo -e "
daemon off;" >> /etc/nginx/nginx.conf
---> Running in a0b04aea9fa3
Removing intermediate container a0b04aea9fa3
---> 423a7c839aa9
Step 5/5 : cmd ["nginx"]
---> Running in 07745803b14d
Removing intermediate container 07745803b14d
---> af5999d77739
Successfully built af5999d77739
Successfully tagged nginx:test01
- 根据镜像创建容器
[root@localhost dock_Files]# docker run --rm --name test -p 80:80 nginx:test01
- 查看端口,并访问
[root@localhost ~]# ss -antl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 128 *:80 *:*
LISTEN 0 128 [::]:22 [::]:*
## 由于加了端口映射,直接访问本地即可
[root@localhost ~]# curl localhost
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>
</html>
这里访问404,是因为alpine安装的linux默认测试页面,需要自行配置
dockerfile——源码配置nginx
- 主机创建容器路径
[root@localhost nginx_dock_Files]# tree
.
├── dockerfile
├── shell
└── soft
└── nginx-1.18.0.tar.gz
- 编写dockerfile
FROM alpine
# 基础元信息
LABEL MAINTAINER='sawyer 121692881@qq.com'
# 镜像操作
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories && apk update
## 安装必备组件
ADD soft/nginx-1.18.0.tar.gz /usr/src/
RUN apk add wget gcc g++ make pcre pcre-tools pcre-dev zlib-dev
## 编译nginx
RUN cd /usr/src/nginx-1.18.0/ &&
./configure --prefix=/usr/local/nginx &&
make && make install &&
ln -s /usr/local/nginx/sbin/nginx /usr/sbin &&
rm -rf /usr/src/nginx*
# 启动nginx
CMD ["nginx","-g","daemon off;"]
# 端口暴露
EXPOSE 80
- 利用dockerfile创建镜像
[root@localhost nginx_dock_Files]docker build -t nginx:test02 ../nginx_dock_Files/
- 查看镜像,并根据镜像创建并运行容器(映射到本地80端口)
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx test02 166b2ea89dc5 5 minutes ago 223MB
nginx test01 af5999d77739 24 hours ago 8.77MB
busybox latest a77dce18d0ec 13 days ago 1.24MB
alpine latest 389fef711851 3 weeks ago 5.58MB
httpd latest dd85cdbb9987 4 weeks ago 138MB
nginx stable 05f64a802c26 4 weeks ago 133MB
ubuntu latest f643c72bc252 6 weeks ago 72.9MB
[root@localhost nginx_dock_Files]# docker run --name test -p 80:80 nginx:test02
- 测试页面
[root@localhost ~]# ss -antl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 128 *:80 *:*
LISTEN 0 128 [::]:22 [::]:*
[root@localhost ~]# curl localhost
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
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>
......