小白手套的 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

# 步骤一:构建,基于 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 ,即阶段来进行
docker build --target  [name] -t imagename:tag .

使用已有镜像作为阶段

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

结语

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

祝你好运

  • 16
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Dockerfile是一个文本文件,它包含了用于自动化构建Docker镜像的指令集合。这些指令告诉Docker从基础镜像开始,如何安装软件、配置环境和复制文件。使用Dockerfile可以让开发者在不同环境中创建一致的软件部署,极大地提升了可移植性和复用性。 以下是使用Dockerfile的基本步骤: 1. **初始化Dockerfile**: 开始Dockerfile时,通常使用`FROM`指令指定基础镜像,如`FROM ubuntu:latest`或`FROM node:14-alpine`。 2. **运行命令(RUN)**: 在这个部分,你可以添加执行的命令,例如安装软件包、设置环境变量或下载文件。 ```bash RUN apt-get update && apt-get install -y nginx ``` 3. **复制文件(COPY)**: 将本地文件复制到镜像中。如果需要创建目录,可以先使用`mkdir`。 ```bash COPY . /app ``` 4. **暴露端口(EXPOSE)**: 如果应用有公开的网络端口,用`EXPOSE 80`声明。 5. **设置工作目录(WORKDIR)**: 指定容器内的默认工作目录。 6. **添加启动命令(CMD/ENTRYPOINT)**: 使用`CMD`设置默认命令,`ENTRYPOINT`更灵活,可以接受参数。 ```bash CMD ["nginx", "-g", "daemon off;"] ``` 7. **构建镜像(docker build)**: 在主机上,使用`docker build -t myimage .`命令,其中`-t`指定标签,`.`表示当前目录作为Dockerfile的位置。 构建完成后,你可以使用`docker run`命令运行基于新镜像的容器,或者使用`docker push`将镜像推送到Docker Hub或其他仓库,以便其他人也能使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不懂前端的运维不是好架构

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值