3、Docker容器化部署:Docker安装与配置、编写Dockerfile、构建镜像、使用Docker Compose编排多容器服务
聊到低代码平台的部署,Docker 几乎是绕不开的坎。说实话,我见过太多团队在部署环节翻车,环境不一致、依赖冲突、版本混乱……这些问题说白了,都是「在我机器上能跑」惹的祸。Docker 就是来解决这个痛点的。
这一章,我会带你从零开始,把 Docker 这套东西捋清楚。安装、写 Dockerfile、构建镜像、再到用 Compose 编排多服务,一步不落。
3.1 Docker 安装与配置
先说说安装。不同操作系统,安装方式略有差异。我个人习惯在 Linux 上搞生产环境,但开发机用 macOS 或 Windows 也没问题。
Linux(CentOS 7+ / Ubuntu 20.04+)
嗯,这里我以 Ubuntu 为例。命令很简单,但有几个坑要注意。
# 卸载旧版本
sudo apt-get remove docker docker-engine docker.io containerd runc
# 安装依赖
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg lsb-release
# 添加 Docker 官方 GPG 密钥
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
# 设置稳定版仓库
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 安装 Docker Engine
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin
sudo usermod -aG docker $USER
newgrp docker # 或者退出重新登录
验证安装
docker --version
docker run hello-world
看到 Hello from Docker! 就说明成了。如果卡住,多半是网络问题。你想想看,国内访问 Docker Hub 有时候确实慢,建议配个镜像加速器。
配置镜像加速器
编辑 /etc/docker/daemon.json,没有就新建一个。
{
"registry-mirrors": ["https://你的加速器地址.mirror.aliyuncs.com"]
}
然后重启 Docker:
sudo systemctl daemon-reload
sudo systemctl restart docker
3.2 编写 Dockerfile
Dockerfile 就是构建镜像的「配方」。说白了,你告诉 Docker 要用什么基础镜像、装什么依赖、复制哪些文件、启动什么命令。
拿一个典型的 Node.js 低代码后端服务举例:
# 基础镜像,选 alpine 版本,体积小
FROM node:18-alpine
# 设置工作目录
WORKDIR /app
# 复制 package.json 和 package-lock.json
COPY package*.json ./
# 安装依赖
RUN npm install --production
# 复制源码
COPY . .
# 暴露端口
EXPOSE 3000
# 启动命令
CMD ["node", "server.js"]
这里有个细节:先复制 package.json,再复制源码。为什么?因为 Docker 构建是有缓存的。如果源码改了但依赖没变,npm install 这步就不会重新执行,能省不少时间。我在项目中遇到过好几次,同事把 COPY . . 写在前面,每次改一行代码都要重新装一遍依赖,气得直跺脚。
多阶段构建
对于编译型语言(比如 Java、Go),多阶段构建是标配。看个 Go 的例子:
# 第一阶段:编译
FROM golang:1.20 AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN go build -o myapp .
# 第二阶段:运行
FROM alpine:3.18
WORKDIR /app
COPY --from=builder /app/myapp .
EXPOSE 8080
CMD ["./myapp"]
最终镜像只有十几兆,干净利落。你想想看,如果不用多阶段构建,一个 Go 镜像可能带一堆编译工具,体积直奔 1GB,部署起来多难受。
3.3 构建镜像
Dockerfile 写好了,就该构建了。
docker build -t my-lowcode-backend:v1.0 .
-t 是给镜像打标签,格式是 名称:版本。最后的 . 表示构建上下文是当前目录。
构建过程中,你会看到每一层(Layer)的执行日志。如果某一步报错,别慌,看日志定位问题。我经常遇到的是 npm install 超时,换个镜像源或者加个 --registry 参数就好。
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
my-lowcode-backend v1.0 abc123def456 2 minutes ago 142MB
3.4 使用 Docker Compose 编排多容器服务
低代码平台通常不止一个服务。前端、后端、数据库、Redis、消息队列……你总不能一个个手动启动吧?Docker Compose 就是干这个的。
在项目根目录下创建 docker-compose.yml:
version: '3.8'
services:
# 后端服务
backend:
build: ./backend
ports:
- "3000:3000"
environment:
- DB_HOST=db
- REDIS_HOST=redis
depends_on:
- db
- redis
# 前端服务
frontend:
build: ./frontend
ports:
- "80:80"
depends_on:
- backend
# 数据库
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root123
MYSQL_DATABASE: lowcode
volumes:
- db_data:/var/lib/mysql
ports:
- "3306:3306"
# 缓存
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
db_data:
这个文件定义了四个服务。注意 depends_on 字段,它控制启动顺序。不过说实话,depends_on 只保证容器启动顺序,不保证服务就绪。比如数据库容器启动了,但 MySQL 还没初始化完成,后端连上去就会报错。我曾经踩过这个坑,后来加了 wait-for-it.sh 脚本才解决。
启动所有服务
docker compose up -d
-d 是后台运行。想看日志就 docker compose logs -f。
常用命令
| 命令 | 说明 |
|---|---|
docker compose up -d |
启动所有服务 |
docker compose down |
停止并删除容器、网络 |
docker compose ps |
查看服务状态 |
docker compose logs -f |
实时查看日志 |
docker compose exec backend sh |
进入某个容器 |
docker compose up(不加 -d),方便看实时日志。生产环境用 docker compose up -d,配合 systemd 做自启动。
3.5 避坑指南
最后,分享几个我踩过的坑:
- 镜像体积过大:尽量用 alpine 版本,多阶段构建,清理不必要的缓存文件。
- 时区问题:默认是 UTC 时间,日志时间对不上。在 Dockerfile 里加一行
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime。 - 数据持久化:数据库、日志文件一定要挂载 volume,否则容器删了数据就没了。我曾经手抖
docker compose down -v把数据库 volume 也删了,还好有备份…… - 网络不通:Compose 会自动创建网络,服务名就是 hostname。但如果你手动指定了 network,记得检查配置。
嗯,这一章的内容就到这里。Docker 容器化部署,说白了就是把你的应用「打包」成标准化的单元,走到哪都能跑。下一章我们会聊镜像仓库和 CI/CD 集成,到时候这些镜像就能自动构建、自动发布了。