Docker镜像制作最佳实践

浏览量:445

镜像制作最佳实践

Docker 是用于构建、分发、运行容器的平台和工具。在当下非常流行,已经是事实上的标准。
使用Docker制作镜像有一些注意事项,下面列出总结出的几点:

1. 使用官方的镜像作为基础镜像

官方的镜像更稳定也更符合标准

2. 基础镜像的标签不要使用latest

如果我们需要一个mysql镜像,打开 https://hub.docker.com/_/mysql

发现描述中会列出支持的标签

Supported tags and respective Dockerfile links
8.0.27, 8.0, 8, latest
5.7.36, 5.7, 5
5.6.51, 5.6

说明下面的命令是等价的

docker pull mysql:latest
docker pull mysql:8.0.27
docker pull mysql:8.0
docker pull mysql:8

但是使用docker pull mysql:8.0 比 docker pull mysql:latest 更具体,也不容易出错

3. 使用.dockerignore 文件

.dockerignore文件用于忽略在构建镜像过程中用不到的文件,可以大大减少镜像的体积
比如构建前端项目,可以将node_modules放到.dockerignore文件里

4. 充分利用缓存机制

看下面的Dockerfile

优化前

FROM node:17.0.1-alpine
WORKDIR /app
COPY myapp /app
RUN npm install --production
CMD ["node", "src/index.js"]

优化后

FROM node:17.0.1-alpine
WORKDIR /app
COPY package.json package-lock.json .
RUN npm install --production
COPY myapp /app
CMD ["node", "src/index.js"]

Docker镜像是由一系列层来构成的,每层代表Dockerfile中的一条指令
比如执行FROM node:17.0.1-alpine后会产生一堆文件,这些文件会缓存都本地,其他Dockerfile也使用了这行命令,就不用重新下载了。

关于COPY命令,如果文件发生了变动会重新构建该层,某层发生了变化其下面的层都要重新构建

明白了这点,记住一个结论就是越容易产生文件变化的命令越放到后面执行

copy myapp /app 放到后面,因为myapp是源码目录,是会经常发生变动的,一旦该层内容发生变动,那么后续的层都会重新执行

这是优化后的执行顺序

5. dockerfile中每行命令产生一层,请最大限度减少层数

当Dockerfile的指令修改了,复制的文件变化了,或者构建镜像时指定的变量不同了,对应的镜像层缓存就会失效。某一层的镜像缓存失效之后,它之后的镜像层缓存都会失效

6. 使用多步构建 multi staging

这是一个前端的通用Dockerfile
分两个stage,一个stage引入node构建前端资源,第二个stage引入nginx托管静态资源
最终运行的只是一个安装了nginx容器,node只是临时的

# build stage
FROM node:lts-alpine as build-stage
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

# production stage
FROM nginx:stable-alpine as production-stage
COPY --from=build-stage /dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

7. 不要使用root用户 避免潜在的风险

某些官方镜像已经为我们创建好了用户,比如node

8. 使用 docker scan 命令扫描风险

该命令非常简单docker scan [image-name], 是利用snyk 提供的服务 不过现在有次数限制

参考

https://www.youtube.com/watch?v=8vXoMqWgbQQ

https://www.qikqiak.com/post/dockerfile-best-practice/

留下评论