从构建到上线:一套可直接照搬的 Docker 自动化工作流指南
Docker 工作流自动化教程|附完整命令
在现代软件开发中,Docker 已经成为开发、测试、部署环节中非常重要的基础工具。它可以帮助我们把应用程序及其依赖环境打包成镜像,并通过容器的方式在不同机器上稳定运行。相比传统部署方式,Docker 的优势在于环境一致、启动快速、易于迁移,并且非常适合与自动化脚本、CI/CD 平台结合,构建标准化的软件交付流程。
本文将围绕 Docker 工作流自动化 展开,介绍从项目容器化、镜像构建、容器运行、数据持久化、多服务编排,到自动化脚本与 CI/CD 集成的完整流程。文章中会附带大量可直接使用的命令,适合希望系统掌握 Docker 自动化工作流的开发者、测试人员、运维工程师阅读。
一、为什么要做 Docker 工作流自动化?
在没有 Docker 或自动化流程之前,一个项目从开发到上线通常会遇到以下问题:
-
环境不一致
开发环境、测试环境、生产环境的软件版本不同,例如 Node.js、Java、MySQL、Redis 版本不一致,导致“我电脑上能运行”的问题频繁出现。 -
部署步骤复杂
每次发布都需要手动拉代码、安装依赖、修改配置、启动服务,步骤多且容易出错。 -
回滚困难
如果新版本发布失败,传统方式可能需要手动恢复代码、配置和依赖,风险较高。 -
多服务管理困难
现代项目通常包含 Web 服务、数据库、缓存、消息队列等多个服务,手动管理启动顺序和网络配置成本较高。 -
缺少标准化交付流程
不同成员的部署方式不同,难以形成可复制、可追踪、可审计的交付链路。
Docker 工作流自动化的目标,就是通过 Dockerfile、Docker Compose、Shell 脚本和 CI/CD 工具,将这些步骤标准化,让项目从构建、测试到部署都可以通过命令自动完成。
二、准备工作:安装 Docker
在开始之前,需要先安装 Docker。不同系统安装方式略有不同。
1. Ubuntu 安装 Docker
sudo apt update
sudo apt install -y ca-certificates curl gnupg lsb-release
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
查看 Docker 是否安装成功:
docker version
查看 Docker Compose 是否可用:
docker compose version
2. CentOS 安装 Docker
sudo yum install -y yum-utils
sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo systemctl start docker
sudo systemctl enable docker
验证安装:
docker version
docker compose version
3. 免 sudo 使用 Docker
默认情况下,普通用户执行 Docker 命令可能需要 sudo。可以将当前用户加入 docker 用户组:
sudo usermod -aG docker $USER
然后重新登录终端,执行:
docker ps
如果不再提示权限错误,则配置成功。
三、Docker 基础命令速览
在自动化工作流中,最常用的是镜像、容器、网络、数据卷相关命令。
1. 镜像相关命令
查看本地镜像:
docker images
拉取镜像:
docker pull nginx:latest
docker pull mysql:8.0
docker pull redis:7
删除镜像:
docker rmi nginx:latest
强制删除镜像:
docker rmi -f nginx:latest
构建镜像:
docker build -t my-app:1.0 .
查看镜像构建历史:
docker history my-app:1.0
2. 容器相关命令
运行容器:
docker run -d --name my-nginx -p 8080:80 nginx:latest
查看运行中的容器:
docker ps
查看所有容器:
docker ps -a
停止容器:
docker stop my-nginx
启动容器:
docker start my-nginx
重启容器:
docker restart my-nginx
删除容器:
docker rm my-nginx
强制删除运行中的容器:
docker rm -f my-nginx
查看容器日志:
docker logs my-nginx
实时查看日志:
docker logs -f my-nginx
进入容器:
docker exec -it my-nginx /bin/bash
如果容器内没有 bash,可以使用 sh:
docker exec -it my-nginx sh
3. 数据卷相关命令
创建数据卷:
docker volume create mysql_data
查看数据卷:
docker volume ls
查看数据卷详情:
docker volume inspect mysql_data
删除数据卷:
docker volume rm mysql_data
清理未使用的数据卷:
docker volume prune
4. 网络相关命令
查看网络:
docker network ls
创建网络:
docker network create app_network
查看网络详情:
docker network inspect app_network
删除网络:
docker network rm app_network
四、项目容器化:编写 Dockerfile
Dockerfile 是 Docker 自动化工作流的核心文件。它描述了如何从基础镜像开始,安装依赖、复制代码、设置环境变量、暴露端口并启动应用。
下面以一个 Node.js 项目为例,假设项目结构如下:
my-node-app/
├── package.json
├── package-lock.json
├── src/
│ └── index.js
└── Dockerfile
1. 示例 Dockerfile
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install --production
COPY . .
EXPOSE 3000
CMD ["node", "src/index.js"]
说明:
FROM node:20-alpine:使用 Node.js 20 的轻量级 Alpine 镜像。WORKDIR /app:设置容器内工作目录。COPY package*.json ./:先复制依赖文件,有利于利用 Docker 构建缓存。RUN npm install --production:安装生产依赖。COPY . .:复制项目代码。EXPOSE 3000:声明容器服务端口。CMD:容器启动时执行的命令。
2. 构建镜像
在项目根目录执行:
docker build -t my-node-app:1.0 .
如果需要禁用缓存重新构建:
docker build --no-cache -t my-node-app:1.0 .
3. 运行容器
docker run -d \
--name my-node-app \
-p 3000:3000 \
my-node-app:1.0
访问应用:
curl http://localhost:3000
查看日志:
docker logs -f my-node-app
停止并删除容器:
docker stop my-node-app
docker rm my-node-app
五、使用 .dockerignore 提升构建效率
在构建镜像时,如果项目目录中包含 node_modules、日志文件、Git 文件等无关内容,会增加镜像构建上下文大小,降低构建速度。此时应使用 .dockerignore 文件。
示例:
node_modules
npm-debug.log
Dockerfile
.dockerignore
.git
.gitignore
logs
*.log
.env
dist
coverage
注意:是否忽略 dist 取决于项目构建方式。如果你的应用需要先构建再复制构建产物,则不要随意忽略 dist。
六、使用 Docker Compose 编排多服务
对于真实项目而言,往往不仅有一个应用服务,还会包含数据库、缓存、消息队列等。此时可以使用 Docker Compose 来编排多个容器。
假设我们有一个后端服务、MySQL 和 Redis,可以编写 docker-compose.yml:
services:
app:
build:
context: .
dockerfile: Dockerfile
image: my-node-app:1.0
container_name: my-node-app
ports:
- "3000:3000"
environment:
NODE_ENV: production
DB_HOST: mysql
DB_PORT: 3306
DB_USER: root
DB_PASSWORD: 123456
DB_NAME: app_db
REDIS_HOST: redis
REDIS_PORT: 6379
depends_on:
- mysql
- redis
networks:
- app_network
mysql:
image: mysql:8.0
container_name: my-mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: 123456
MYSQL_DATABASE: app_db
ports:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql
networks:
- app_network
redis:
image: redis:7-alpine
container_name: my-redis
restart: always
ports:
- "6379:6379"
networks:
- app_network
volumes:
mysql_data:
networks:
app_network:
driver: bridge
常用 Compose 命令
启动所有服务:
docker compose up -d
启动并重新构建镜像:
docker compose up -d --build
查看服务状态:
docker compose ps
查看所有服务日志:
docker compose logs
实时查看日志:
docker compose logs -f
查看某个服务日志:
docker compose logs -f app
停止服务:
docker compose stop
启动已停止服务:
docker compose start
重启服务:
docker compose restart
停止并删除容器、网络:
docker compose down
同时删除数据卷:
docker compose down -v
七、使用环境变量文件管理配置
不建议把数据库密码、密钥等敏感信息直接写在 docker-compose.yml 中。更好的方式是使用 .env 文件。
创建 .env:
NODE_ENV=production
APP_PORT=3000
MYSQL_ROOT_PASSWORD=123456
MYSQL_DATABASE=app_db
MYSQL_PORT=3306
REDIS_PORT=6379
修改 docker-compose.yml:
services:
app:
build: .
image: my-node-app:1.0
container_name: my-node-app
ports:
- "${APP_PORT}:3000"
environment:
NODE_ENV: ${NODE_ENV}
DB_HOST: mysql
DB_PORT: 3306
DB_USER: root
DB_PASSWORD: ${MYSQL_ROOT_PASSWORD}
DB_NAME: ${MYSQL_DATABASE}
REDIS_HOST: redis
REDIS_PORT: 6379
depends_on:
- mysql
- redis
mysql:
image: mysql:8.0
container_name: my-mysql
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
ports:
- "${MYSQL_PORT}:3306"
volumes:
- mysql_data:/var/lib/mysql
redis:
image: redis:7-alpine
container_name: my-redis
ports:
- "${REDIS_PORT}:6379"
volumes:
mysql_data:
启动时 Docker Compose 会自动读取同目录下的 .env 文件:
docker compose up -d
如果想指定环境变量文件:
docker compose --env-file .env.production up -d
八、编写自动化脚本
为了减少重复命令,可以把常用操作封装为 Shell 脚本。例如创建 deploy.sh:
#!/usr/bin/env bash
set -e
APP_NAME="my-node-app"
IMAGE_NAME="my-node-app"
IMAGE_TAG="1.0"
echo "开始构建镜像..."
docker build -t ${IMAGE_NAME}:${IMAGE_TAG} .
echo "停止旧容器..."
docker rm -f ${APP_NAME} || true
echo "启动新容器..."
docker run -d \
--name ${APP_NAME} \
-p 3000:3000 \
--restart always \
${IMAGE_NAME}:${IMAGE_TAG}
echo "查看容器状态..."
docker ps | grep ${APP_NAME}
echo "部署完成!"
赋予执行权限:
chmod +x deploy.sh
执行部署:
./deploy.sh
如果使用 Docker Compose,可以写成:
#!/usr/bin/env bash
set -e
echo "拉取最新代码..."
git pull
echo "构建并启动服务..."
docker compose up -d --build
echo "清理无用镜像..."
docker image prune -f
echo "当前服务状态:"
docker compose ps
echo "部署完成!"
执行:
chmod +x deploy-compose.sh
./deploy-compose.sh
九、镜像版本管理与回滚
在生产环境中,不建议始终使用 latest 标签,因为它无法准确表示具体版本。推荐使用 Git Commit ID、日期、语义化版本号作为镜像标签。
查看当前 Git Commit:
git rev-parse --short HEAD
构建镜像:
IMAGE_TAG=$(git rev-parse --short HEAD)
docker build -t my-node-app:${IMAGE_TAG} .
同时打一个 latest 标签:
docker tag my-node-app:${IMAGE_TAG} my-node-app:latest
如果需要回滚到指定版本:
docker rm -f my-node-app
docker run -d \
--name my-node-app \
-p 3000:3000 \
--restart always \
my-node-app:旧版本标签
使用 Compose 时,可以在 .env 中定义镜像版本:
IMAGE_TAG=2024-01-01
在 docker-compose.yml 中引用:
services:
app:
image: my-node-app:${IMAGE_TAG}
ports:
- "3000:3000"
部署指定版本:
docker compose --env-file .env.production up -d
十、推送镜像到镜像仓库
自动化部署通常会将镜像推送到 Docker Hub、阿里云容器镜像服务、腾讯云 TCR、Harbor 等镜像仓库。
1. 登录 Docker Hub
docker login
输入用户名和密码或 Token。
2. 标记镜像
docker tag my-node-app:1.0 your-dockerhub-name/my-node-app:1.0
3. 推送镜像
docker push your-dockerhub-name/my-node-app:1.0
4. 在服务器拉取镜像
docker pull your-dockerhub-name/my-node-app:1.0
运行:
docker run -d \
--name my-node-app \
-p 3000:3000 \
--restart always \
your-dockerhub-name/my-node-app:1.0
十一、结合 GitHub Actions 实现自动构建与推送
CI/CD 是 Docker 工作流自动化的重要组成部分。下面以 GitHub Actions 为例,实现代码推送后自动构建 Docker 镜像并推送到 Docker Hub。
在项目中创建文件:
.github/workflows/docker.yml
内容如下:
name: Docker Build and Push
on:
push:
branches:
- main
jobs:
docker:
runs-on: ubuntu-latest
steps:
- name: Checkout source code
uses: actions/checkout@v4
- name: Set image tag
id: vars
run: echo "IMAGE_TAG=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build Docker image
run: |
docker build \
-t ${{ secrets.DOCKERHUB_USERNAME }}/my-node-app:${{ steps.vars.outputs.IMAGE_TAG }} \
-t ${{ secrets.DOCKERHUB_USERNAME }}/my-node-app:latest \
.
- name: Push Docker image
run: |
docker push ${{ secrets.DOCKERHUB_USERNAME }}/my-node-app:${{ steps.vars.outputs.IMAGE_TAG }}
docker push ${{ secrets.DOCKERHUB_USERNAME }}/my-node-app:latest
需要在 GitHub 仓库中配置 Secrets:
DOCKERHUB_USERNAMEDOCKERHUB_TOKEN
这样每次向 main 分支推送代码时,GitHub Actions 就会自动构建镜像并推送到 Docker Hub。
十二、服务器自动拉取并部署
镜像构建和推送完成后,服务器端可以通过脚本拉取镜像并重启服务。
创建 server-deploy.sh:
#!/usr/bin/env bash
set -e
IMAGE="your-dockerhub-name/my-node-app"
TAG="latest"
CONTAINER_NAME="my-node-app"
echo "登录镜像仓库..."
docker login
echo "拉取最新镜像..."
docker pull ${IMAGE}:${TAG}
echo "停止旧容器..."
docker rm -f ${CONTAINER_NAME} || true
echo "启动新容器..."
docker run -d \
--name ${CONTAINER_NAME} \
-p 3000:3000 \
--restart always \
${IMAGE}:${TAG}
echo "清理无用镜像..."
docker image prune -f
echo "部署完成。"
docker ps | grep ${CONTAINER_NAME}
执行:
chmod +x server-deploy.sh
./server-deploy.sh
如果使用 Docker Compose,推荐服务器端 docker-compose.yml 使用远程镜像:
services:
app:
image: your-dockerhub-name/my-node-app:${IMAGE_TAG}
container_name: my-node-app
ports:
- "3000:3000"
restart: always
部署命令:
IMAGE_TAG=latest docker compose up -d
十三、健康检查与自动重启
为了让容器在异常退出时自动恢复,可以使用 --restart 参数:
docker run -d \
--name my-node-app \
-p 3000:3000 \
--restart always \
my-node-app:1.0
常见策略:
| 策略 | 说明 |
|---|---|
no |
默认策略,不自动重启 |
always |
容器退出后总是重启 |
unless-stopped |
除非手动停止,否则自动重启 |
on-failure |
仅在非 0 状态退出时重启 |
在 Compose 中配置:
services:
app:
image: my-node-app:1.0
restart: unless-stopped
也可以在 Dockerfile 中增加健康检查:
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
CMD wget -qO- http://localhost:3000/health || exit 1
查看健康状态:
docker ps
查看详细信息:
docker inspect my-node-app
十四、日志管理与排障命令
Docker 自动化部署之后,排障主要依赖日志和容器状态检查。
查看最近 100 行日志:
docker logs --tail=100 my-node-app
持续查看日志:
docker logs -f my-node-app
查看带时间戳的日志:
docker logs -f -t my-node-app
进入容器检查:
docker exec -it my-node-app sh
查看容器资源占用:
docker stats
查看容器进程:
docker top my-node-app
查看容器详细信息:
docker inspect my-node-app
查看端口映射:
docker port my-node-app
查看容器退出原因:
docker inspect my-node-app --format='{{.State.ExitCode}}'
docker inspect my-node-app --format='{{.State.Error}}'
十五、清理 Docker 资源
长期构建和部署后,服务器上会积累很多未使用的镜像、容器、网络和缓存,需要定期清理。
删除所有停止的容器:
docker container prune
删除未使用镜像:
docker image prune
删除所有未被使用的镜像:
docker image prune -a
删除未使用网络:
docker network prune
删除未使用数据卷:
docker volume prune
一次性清理:
docker system prune
清理更多资源,包括未使用镜像:
docker system prune -a
谨慎执行包含数据卷的清理命令:
docker system prune -a --volumes
生产环境中执行清理前,务必确认不会删除仍需保留的数据卷。
十六、推荐的 Docker 自动化工作流
一个比较完整的 Docker 自动化工作流可以设计为:
- 开发者提交代码到 Git 仓库;
- CI 平台自动拉取代码;
- CI 平台执行测试;
- 测试通过后构建 Docker 镜像;
- 使用 Git Commit ID 或版本号给镜像打标签;
- 推送镜像到镜像仓库;
- 服务器拉取指定版本镜像;
- 使用 Docker Compose 启动或更新服务;
- 检查容器健康状态;
- 如部署失败,快速回滚到旧版本镜像。
对应的核心命令可以概括为:
git pull
docker build -t my-node-app:$(git rev-parse --short HEAD) .
docker tag my-node-app:$(git rev-parse --short HEAD) registry.example.com/my-node-app:$(git rev-parse --short HEAD)
docker push registry.example.com/my-node-app:$(git rev-parse --short HEAD)
docker compose pull
docker compose up -d
docker compose ps
docker compose logs -f
十七、最佳实践总结
为了让 Docker 工作流更加稳定、安全、可维护,建议遵循以下实践:
-
不要在生产环境使用不确定的 latest 标签
可以保留 latest,但生产发布最好使用明确版本号。 -
使用 .dockerignore 减少构建上下文
避免把无关文件复制进镜像。 -
优先使用轻量基础镜像
例如 Alpine、Slim 版本,但也要注意兼容性。 -
敏感配置不要写死在镜像中
使用环境变量、密钥管理工具或 CI/CD Secret。 -
数据库数据必须挂载数据卷
避免容器删除后数据丢失。 -
使用 Docker Compose 管理多服务项目
比手写多个docker run命令更清晰、更容易维护。 -
部署前保留旧版本镜像
出现问题时可以快速回滚。 -
定期清理无用资源
防止磁盘被构建缓存和旧镜像占满。 -
为服务增加健康检查
方便自动化平台判断服务是否正常。 -
将常用操作封装成脚本
例如构建、推送、部署、回滚、清理等,提高效率并降低人为错误。
十八、完整命令清单
下面整理一份常用 Docker 自动化命令清单,方便快速查阅。
Docker 安装检查
docker version
docker info
docker compose version
镜像操作
docker pull nginx:latest
docker images
docker build -t my-app:1.0 .
docker build --no-cache -t my-app:1.0 .
docker tag my-app:1.0 registry.example.com/my-app:1.0
docker push registry.example.com/my-app:1.0
docker rmi my-app:1.0
容器操作
docker run -d --name my-app -p 3000:3000 --restart always my-app:1.0
docker ps
docker ps -a
docker logs -f my-app
docker exec -it my-app sh
docker stop my-app
docker start my-app
docker restart my-app
docker rm -f my-app
Compose 操作
docker compose up -d
docker compose up -d --build
docker compose ps
docker compose logs -f
docker compose restart
docker compose stop
docker compose down
docker compose down -v
网络与数据卷
docker network ls
docker network create app_network
docker network inspect app_network
docker network rm app_network
docker volume ls
docker volume create mysql_data
docker volume inspect mysql_data
docker volume rm mysql_data
清理命令
docker container prune
docker image prune
docker image prune -a
docker network prune
docker volume prune
docker system prune
docker system prune -a
结语
Docker 工作流自动化的本质,是把原本依赖人工经验的部署过程,转化为可重复、可追踪、可回滚的标准流程。通过 Dockerfile,我们可以统一应用运行环境;通过 Docker Compose,我们可以管理多服务依赖;通过 Shell 脚本,可以减少重复操作;通过 CI/CD,可以进一步实现从代码提交到镜像构建、推送和部署的自动化闭环。
对于个人项目来说,Docker 可以显著降低环境配置成本;对于团队项目来说,Docker 能够提高交付一致性;对于生产系统来说,Docker 自动化工作流能够提升部署效率和系统稳定性。
如果你刚开始实践 Docker,建议先从单服务 Dockerfile 入手,再逐步引入 Compose、镜像仓库和 CI/CD。只要把这些环节串联起来,就可以形成一套真正可落地的 Docker 自动化交付体系。