小白手套的 Docker 奇幻旅行之 Dockerfile 可以写多个 FROM ?

特殊的需求

小白手套吐槽,我们这小公司,啥啥没有,小李还需要使用容器作为部署环境,但没有运维的支持

  • 项目 N 多,每个项目需要的环境又不一样

  • 我每次需要手动编译我的项目,再自己找到 Dockerfile 生成可部署的镜像,真的好麻烦,有什么黑科技可以帮我解决自动编译并且构建为镜像呢 ?

Multi-stage builds

通过多阶段构建,可以FROM在 Dockerfile 中使用多个语句。每条FROM指令可以使用不同的基础,并且每条指令都开始构建的新阶段。可以有选择地将工件从一个阶段复制到另一个阶段,从而在最终镜像中留下不想要的所有内容。

有没有感觉上面的关键词,阶段,有点像流水线呢?流水线运行过程中会注入 N 多依赖,比如 基于我的基础环境,可能做一些代码检查,代码编译等动作,但最终是为了拿到一个可以部署的包,那么最终部署环境又不需要依赖编译环境,这样就造成了我的镜像越来越大的问题。(当然,Multi-stage 并不是唯一方案,只是对于有镜像优化需求的人来讲,可能更有用)

Docker Multi-stage builds 的出现核心是为了优化镜像大小和减少不必要的依赖,那么我们也可以基于多阶段构建这个特性,来完成一个伪 CI (自动编译+打出一个可以部署的镜像)二合一的 Dockerfile

实际操作

下面的流程为:

1、我需要一个 Node 环境满足我的编译场景,编译后将 dist 文件作为产出物

2、将 dist 文件加入我的 Apache (即一个 web 服务器),最后启动镜像可以成功访问我的页面

基础项目(一个简单的 blog 页面)

编写 Dockerfile

bash 复制代码
# 步骤一:构建,基于 node 21.5.0
FROM node:21.5.0 AS build
# 设置工作目录
WORKDIR /usr/src/app
# 将源码复制到容器环境
COPY . .
# 编译源码
RUN npm install pnpm -g && pnpm install --force && pnpm docs:build

# 步骤二:成品,将产出物添加至 Apache 服务器
FROM httpd:2.4-alpine
# 设置工作目录
WORKDIR /usr/local/apache2/htdocs/
# 将上一个阶段 dist 复制到当前阶段
COPY --from=build /usr/src/app/src/.vuepress/dist .
# 声明 80 端口
EXPOSE 80
# 启动服务器
CMD ["httpd-foreground"]

构建镜像并运行

访问

访问 localhost:8088 可以看到

Multi-stage builds 进阶玩法

停止在特定的阶段

  • 比如我 Dockerfile 中有 10 个步骤,比如想对中间第 5 个步骤进行调试,此时就可以通过指定 name ,即阶段来进行
bash 复制代码
docker build --target  [name] -t imagename:tag .

使用已有镜像作为阶段

  • 比如 我想要某个大神写的 mysql.cnf 配置文件作为我自己的配置,但我不想用他的镜像本身
bash 复制代码
COPY --from=mysql-diy:latest /etc/mysql/my.cnf  /etc/mysql/my.cnf

结语

multi-stage 的出现是为了协助你写出更小体积的镜像,将复杂的镜像通过阶段清晰化。也可以利用这个特性协助你完成更高效的交付。multi-stage 不是银弹,一切存在即合理。

祝你好运

相关推荐
开心就好20251 分钟前
iOS 抓包工具在不同场景的实际作用
后端
遇见火星3 分钟前
Docker Compose 实战教程,理解Docker Compose核心概念,学会编写 compose.yml,掌握常用命令!
运维·docker·容器·compose
原神启动15 分钟前
Docker(二)—— Docker容器操作
运维·docker·容器
廋到被风吹走7 分钟前
【Spring】核心类研究价值排行榜
java·后端·spring
呼啦啦呼啦啦啦啦啦啦22 分钟前
推送docker镜像至私有 Docker 镜像仓库(附企业harbor实战)
运维·docker·容器
m0_4856146724 分钟前
Docker基础
docker·容器·php
czlczl2002092529 分钟前
SpringBoot实践:从验证码到业务接口的完整交互生命周期
java·spring boot·redis·后端·mysql·spring
爱学大树锯40 分钟前
【Docker本地化超级实践】Docker 镜像离线构建方案
运维·docker·容器
天天摸鱼的java工程师41 分钟前
Kafka 消息积压处理实战:百万级队列清空的优化技巧
java·后端
默恋~微凉1 小时前
Docker
运维·docker·容器