dockerfile
Dockerfie 官方文档:https://docs.docker.com/engine/reference/builder/
Dockerfile 最佳实践文档:https://docs.docker.com/develop/develop-images/dockerfile_best-practices/
Docker 官方镜像 Dockerfile:https://github.com/docker-library/docs
忽略文件:.dockerignore
我的镜像
# 构建
FROM node:22-slim
# 生产
FROM node:22-alpine
FROM registry.cn-chengdu.aliyuncs.com/qins-img/node:22-alpine
FROM nginx:1.24-alpine
FROM registry.cn-chengdu.aliyuncs.com/qins-img/nginx:1.24-alpinecommand 说明
例 1
FROM node:8.4
COPY . /app
WORKDIR /app
RUN npm install --registry=https://registry.npm.taobao.org
EXPOSE 3000FROM:指定基础镜像
使用 Alpine 镜像
WORKDIR:指定工作目录
影响后续所有的命令(如 RUN, CMD, ENTRYPOINT, COPY, ADD 等)的相对路径。
WORKDIR 例
FROM node:18
# 设置工作目录
WORKDIR /usr/src/app
# 将项目文件拷贝到工作目录
COPY package*.json ./
RUN npm install
COPY . .
# 默认执行命令(会在 /usr/src/app 下执行)
CMD ["node", "server.js"]每个新的 WORKDIR 都是基于前一个目录的。例如:
WORKDIR /app
WORKDIR logs
# 实际路径为 /app/logsCOPY:从 构建上下文(build context)复制到 dest(WORKDIR)
RUN:把命令的结果写进镜像层里。
每一个 RUN 都会创建一个新的镜像层。
EXPOSE:声明端口
CMD / ENTRYPOINT:一般都是用于启动
CMD 会被 docker run 后面的命令覆盖,ENTRYPOINT 只会附加。
信息
CMD ["node", "index.js"]docker run myimage node b.js
# 此时就会发生覆盖,最终效果为:
node b.jsENTRYPOINT ["node","index.js"]docker run myimage --port 3000
# 等同于
node index.js --port 3000ENV:设置环境
ENV MYSQL_ROOT_PASSWORD=123456 \
MYSQL_DATABASE="test" \
MYSQL_USER=test \
MYSQL_PASSWORD=123456不常用:
ADD:优先使用 COPY
ARG:和 ENV 很像,构建时的环境变量
VOLUME:设置 匿名卷
VOLUME /datadocker run -d -v mydata:/data xxxxUSER:指定用户
HEALTHCHECK:通过指定一行命令,来判断容器主进程的服务状态是否还正常
HEALTHCHECK [选项] CMD <命令>命令的返回值决定了是否健康
- 0:成功;
- 1:失败
- 2:保留。不要用 2
SHELL:指定 shell
默认是 ["/bin/sh", "-c"]
LABEL:以键值对的形式添加一些元数据
ONBUILD:不会执行,只有当前 image 被作为其他镜像基础镜像时候,才会生效
最佳实践
1、 Dockerfile 应该足够快,创建 container 和部署的工作量应该小。
2、层数尽可能少。
3、多行参数排序。如:
RUN apt-get update && apt-get install -y \
bzr \
cvs \
git \
mercurial \
subversion4、一个容器中只运行一个进程。 web 应用、数据库、Redis 应该是三个镜像。
多阶段构建
多阶段构建:https://vuepress.mirror.docker-practice.com/image/multistage-builds/#
构建缓存
复用之前构建过程中生成的中间镜像层(layer)。
Docker 会逐行读取 Dockerfile 并依次执行每条指令,每条指令构建出一个镜像层。如果该层之前已构建过且内容完全一致,Docker 就会使用缓存层,跳过重新执行。
构建缓存只存在于本地。
FROM node:20
WORKDIR /app
COPY package.json . # ✅ 如果 package.json 没变,则命中缓存
RUN npm install # ✅ 如果上一步命中缓存,也会命中
COPY . . # ❌ 如果代码变动,则这一层和后面都会失效
RUN npm run build # ❌ 因为上一层已失效,所以这一步也会执行关闭缓存:
docker build --no-cache