Dockerfile 使用技巧篇

默认的 docker 镜像使用 Linux 来当作基础镜像

01. 使用 alpine 镜像,而不是默认的 linux 镜像

PS: alpine 译为高山植物,就是很少的资源就能存活的意思。alpine 裁剪了很多不必要的 linux 功能,使得镜像体积大幅减小了。

  1. 比如 FROM node:18 可改为 FROM node:18-alpine3.14

Dockerfile 会给每一行都增加缓存,所以尽可能的复用缓存可以提高速度,另外就是源码和很多构建的依赖是不需要的,但是现在都保存在了镜像里。比如 Vue 项目实际上我们只需要构建出来的 ./dist 目录下的文件还有运行时的依赖。

02. 使用多阶段构建

  1. 例子
FROM node:18-alpine3.14 as build-stage

WORKDIR /app

COPY package.json .

RUN npm install

COPY . .

RUN npm run build

#production stage
FROM node:18-alpine3.14 as production-stage

COPY --from=build-stage /app/dist /app
COPY --from=build-stage /app/package.json /app/package.json

WORKDIR /app

RUN npm install --production

EXPOSE 3000

CMD ["node", "/app/main.js"]

FROM 后面添加一个 as 来指定当前构建阶段的名字。
通过 COPY --from=xxx 可以从上个阶段复制文件过来。
然后 npm install 的时候添加 --production,这样只会安装 dependencies 的依赖。
docker build 之后,只会留下最后一个阶段的镜像。
也就是说,最终构建出来的镜像里是没有源码的,有的只是 dist 的文件和运行时依赖。
这样镜像就会小很多。

03. 使用 ARG 增加构建灵活性

  1. 例子
FROM node:18-alpine3.14

ARG aaa
ARG bbb

WORKDIR /app

COPY ./test.js .

ENV aaa=${aaa} \
    bbb=${bbb}

CMD ["node", "/app/test.js"]

使用 ARG 声明构建参数,使用 ${xxx} 来取

然后用 ENV 声明环境变量。

dockerfile 内换行使用 \

之后构建的时候传入构建参数:

docker build --build-arg aaa=3 --build-arg bbb=4 -t arg-test -f 333.Dockerfile .

通过 --build-arg xxx=yyy 传入 ARG 参数的值。

04. CMD 结合 ENTRYPOINT

前面的 CMD 其实可以换成 ENTRYPOINT。
这两种写法有什么区别么?

  1. 用 CMD 的时候,启动命令是可以重写的
  2. ENTRYPOINT 不会也不能重写命令

05. COPY vs ADD

这俩都可以把宿主机的文件复制到容器内。但有一点区别,就是对于 tar.gz 这种压缩文件的处理上:
ADD、COPY 都可以用于把目录下的文件复制到容器内的目录下。但是 ADD 还可以解压 tar.gz 文件。
一般情况下,还是用 COPY 居多。

总结下来

Dockerfile 有挺多技巧:

  • 使用 alpine 的镜像,而不是默认的 linux 镜像,可以极大减小镜像体积,比如 node:18-alpine3.14 这种
  • 使用多阶段构建,比如一个阶段来执行 build,一个阶段把文件复制过去,跑起服务来,最后只保留最后一个阶段的镜像。这样使镜像内只保留运行需要的文件以及 dependencies。
  • 使用 ARG 增加构建灵活性,ARG 可以在 docker build 时通过 --build-arg xxx=yyy 传入,在 dockerfile 中生效,可以使构建过程更灵活。如果是想定义运行时可以访问的变量,可以通过 ENV 定义环境变量,值使用 ARG 传入。
  • CMD 和 ENTRYPOINT 都可以指定容器跑起来之后运行的命令,CMD 可以被覆盖,而 ENTRYPOINT 不可以,两者结合使用可以实现参数默认值的功能。
  • ADD 和 COPY 都可以复制文件到容器内,但是 ADD 处理 tar.gz 的时候,还会做一下解压。

ADD方法会解压压缩包,但是注意太大的文件不要使用ADD方法。docker build的过程会加载到内存里面去。太大的文件使用ADD存在内存问题。
alpine 镜像有部分一些链接文件缺失的。比如golang打包,alpine 镜像中可能会缺少一些C语言的依赖文件。这个时候可以通过COPY复制到容器内。也可以FROM别人制作好的镜像操作。

你可能感兴趣的:(Dockerfile,Linux,基本知识点,Docker,Dockerfile,Linux)