Skip to content

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

我的镜像

sh
# 构建
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-alpine

command 说明

例 1

dockerfile
FROM node:8.4

COPY . /app
WORKDIR /app

RUN npm install --registry=https://registry.npm.taobao.org

EXPOSE 3000

FROM:指定基础镜像
使用 Alpine 镜像

WORKDIR:指定工作目录
影响后续所有的命令(如 RUN, CMD, ENTRYPOINT, COPY, ADD 等)的相对路径。

WORKDIR 例

dockerfile
FROM node:18

# 设置工作目录
WORKDIR /usr/src/app

# 将项目文件拷贝到工作目录
COPY package*.json ./
RUN npm install

COPY . .

# 默认执行命令(会在 /usr/src/app 下执行)
CMD ["node", "server.js"]

每个新的 WORKDIR 都是基于前一个目录的。例如:

dockerfile
WORKDIR /app
WORKDIR logs

# 实际路径为 /app/logs

COPY:从 构建上下文(build context)复制到 dest(WORKDIR)

RUN:把命令的结果写进镜像层里。
每一个 RUN 都会创建一个新的镜像层。

EXPOSE:声明端口

CMD / ENTRYPOINT:一般都是用于启动

CMD 会被 docker run 后面的命令覆盖,ENTRYPOINT 只会附加。

信息

Dockerfile
CMD ["node", "index.js"]
sh
docker run myimage node b.js
# 此时就会发生覆盖,最终效果为:
node b.js
Dockerfile
ENTRYPOINT ["node","index.js"]
sh
docker run myimage --port 3000
# 等同于
node index.js --port 3000

ENV:设置环境

sh
ENV MYSQL_ROOT_PASSWORD=123456 \
    MYSQL_DATABASE="test" \
    MYSQL_USER=test \
    MYSQL_PASSWORD=123456

不常用:


ADD:优先使用 COPY

ARG:和 ENV 很像,构建时的环境变量

VOLUME:设置 匿名卷

sh
VOLUME /data
sh
docker run -d -v mydata:/data xxxx

USER:指定用户

HEALTHCHECK:通过指定一行命令,来判断容器主进程的服务状态是否还正常

sh
HEALTHCHECK [选项] CMD <命令>

命令的返回值决定了是否健康

  • 0:成功;
  • 1:失败
  • 2:保留。不要用 2

SHELL:指定 shell

默认是 ["/bin/sh", "-c"]

LABEL:以键值对的形式添加一些元数据

ONBUILD:不会执行,只有当前 image 被作为其他镜像基础镜像时候,才会生效

最佳实践

1、 Dockerfile 应该足够快,创建 container 和部署的工作量应该小。

2、层数尽可能少。

3、多行参数排序。如:

docker
RUN apt-get update && apt-get install -y \
  bzr \
  cvs \
  git \
  mercurial \
  subversion

4、一个容器中只运行一个进程。 web 应用、数据库、Redis 应该是三个镜像。

多阶段构建

多阶段构建:https://vuepress.mirror.docker-practice.com/image/multistage-builds/#

构建缓存

复用之前构建过程中生成的中间镜像层(layer)。

Docker 会逐行读取 Dockerfile 并依次执行每条指令,每条指令构建出一个镜像层。如果该层之前已构建过且内容完全一致,Docker 就会使用缓存层,跳过重新执行。

构建缓存只存在于本地。

docker
FROM node:20
WORKDIR /app
COPY package.json .          # ✅ 如果 package.json 没变,则命中缓存
RUN npm install              # ✅ 如果上一步命中缓存,也会命中
COPY . .                     # ❌ 如果代码变动,则这一层和后面都会失效
RUN npm run build            # ❌ 因为上一层已失效,所以这一步也会执行

关闭缓存:

sh
docker build --no-cache