Dockerfile
什么是 Dockerfile?
- Dockerfile 是一个普通的文本文件,文件名字必须是
Dockerfile,里面写了一个新镜像自定义的构建过程。 - 用于在一个基础镜像上增加点自己的东西,比如安装软件、个性化配置等,最后变成一个新镜像。
- ⚠️
存放路径: 这个Dockerfile文件的存放路径一般都是在项目的根目录下。 - 相关命令:
docker build -t 镜像名:标签 .
相关语法指令
| 指令 | 作用 |
|---|---|
| FROM | 定制的镜像都是基于 FROM 的镜像,这里的 nginx 就是定制需要的基础镜像 |
| MAINTAINER | 镜像维护者的姓名和邮箱地址 |
| RUN | 构建镜像时执行的命令 |
| CMD | 容器启动时执行的命令,多个 CMD 只有最后一个生效,可被 docker run 覆盖 |
| LABEL | 为镜像添加元数据标签 |
| EXPOSE | 声明容器运行时提供的端口,仅声明,不发布 |
| ENV | 设置环境变量,构建和运行时都有效 |
| ADD | 复制文件/目录到镜像,支持自动解压 tar、远程下载 |
| COPY | 仅复制本地文件到镜像,官方推荐使用 |
| ENTRYPOINT | 容器启动入口命令,不会被覆盖,可与 CMD 配合使用默认参数 |
| VOLUME | 定义匿名数据卷,用于持久化数据 |
| USER | 指定运行容器时的用户名或 UID |
| WORKDIR | 指定工作目录,后续命令均在此目录执行 |
| ARG | 与 ENV 作用一致。不过作用域不一样。ARG 设置的环境变量仅对 Dockerfile 内有效 |
| ONBUILD | 起初是为了构建自定义的基础镜像,其实用普通命令都能完成,冗余了几乎不会用到 |
| HEALTHCHECK | 容器启动后,定期检查容器健康状态 |
| SHELL | 指定默认使用的 Shell 类型 |
Dockerfile用法案例
案例说明1
- 多说无益,没有什么比一个具体案例更能简单快速理解一个新东西了,如果有,那么就两个。
- 这个案例是在一台linux虚拟机上构建一个nginx博客容器,里面放了我的vitepress静态网页
1. Dockerfile 文件内容
Dockerfile
FROM nginx:latest # 从 nginx 最基础新版本镜像开始定制
# 思考为什么这里用到连接符号\,难道多个LABEL指令不能写吗?下面注意事项解答
LABEL author="华子" \
version="v1.0"\
description="vitepress前端静态站点镜像" # 添加镜像描述信息
WORKDIR /usr/share/nginx/html # 切换到 nginx 静态站点目录
COPY ./.vitepress/dist/ . # 复制 vitepress 生成的静态文件到 nginx 静态站点目录
EXPOSE 80 # 暴露容器运行时提供的端口,仅声明,不发布
ENTRYPOINT ["nginx"] # 容器启动入口命令,不会被覆盖,可与 CMD 配合使用默认参数
CMD ["-g", "daemon off;"] # 容器启动时执行的命令最后添加的cmd可覆盖-g daemon off
# 默认启动命令为:`nginx -g daemon off`
# ENTRYPOINT 和 CMD 经常搭配使用。上面意思,容器启动时会执行一条nginx -g daemon off作为容器的第一主程序
# ENTRYPOINT 命令是固定参数,而CMD是可变的,在启动命令的最后可添加覆盖CMD默认值。第二个例子会说明。 注意事项
- Dockerfile 的指令每执行一次都会在 docker 上新建一层。所以过多无意义的层,会造成镜像膨胀过大。
- 可以一起执行的指令尽量用连接符号
\和&&,避免多个重复指令。
2. 构建镜像
bash
[root@rocky vitepress]# docker build -t myblog:v1.0 . # 构建镜像下面是构建过程不必理会
DEPRECATED: The legacy builder is deprecated and will be removed in a future release.
Install the buildx component to build images with BuildKit:
https://docs.docker.com/go/buildx/
Sending build context to Docker daemon 414.9MB
Step 1/7 : FROM nginx:latest
---> 0cf1d6af5ca7
Step 2/7 : LABEL author="华子" version="v1.0" description="vitepress前端静态站点镜像"
---> Running in c26b8201a3cd
---> Removed intermediate container c26b8201a3cd
---> 67bfca86a447
Step 3/7 : WORKDIR /usr/share/nginx/html
---> Running in f08892aba412
---> Removed intermediate container f08892aba412
---> c4589d878ba1
Step 4/7 : COPY ./.vitepress/dist/ .
---> 81dc06d901ec
Step 5/7 : EXPOSE 80
---> Running in 6064f5f98a60
---> Removed intermediate container 6064f5f98a60
---> c76eb8a73a7d
Step 6/7 : ENTRYPOINT ["nginx"]
---> Running in 5ce898cbde51
---> Removed intermediate container 5ce898cbde51
---> bcd4d60881dc
Step 7/7 : CMD ["-g", "daemon off;"]
---> Running in 9242e950880c
---> Removed intermediate container 9242e950880c
---> 529ae7b4d0d1
Successfully built 529ae7b4d0d1
Successfully tagged myblog:v1.0
[root@rocky vitepress]# docker images # 查看镜像,构建完毕
REPOSITORY TAG IMAGE ID CREATED SIZE
myblog v1.0 529ae7b4d0d1 34 seconds ago 191MB 3. 运行容器
bash
[root@rocky vitepress]# docker run -d --name testblog -p 80:80 myblog:v1.0 # 运行容器
dc545654cac6a2c5030833a905248c9030f982a90907cd2aed2261bb6e097b36
# 虚拟机IP为192.168.73.64 4. 查看效果
案例说明2
ENTRYPOINT和CMD的搭配使用案例CMD命令是可变参数ENTRYPOINT命令是固定参数
bash
[root@rocky vitepress]# docker stop testblog # 停止刚才的容器
testblog
# 再启动一个容器,命令后面加一个-v参数
[root@rocky vitepress]# docker run -d --name test2blog -p 80:80 myblog:v1.0 -v
f091047d51e4b177e85934581ee5469d00cb1515f13e1bd6512970caa2f005ff
# 查看容器状态
[root@rocky vitepress]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f091047d51e4 myblog:v1.0 "nginx -v" 21 seconds ago Exited (0) 21 seconds ago test2blog
dc545654cac6 myblog:v1.0 "nginx -g 'daemon of…" 36 minutes ago Exited (0) 39 seconds ago testblog
# 可以看到第二个容器的COMMAND变成了nginx -v ,第一个容器的COMMAND是nginx -g daemon off;