上一篇 下一篇 分享链接 返回 返回顶部

从构建到上线:一套可直接照搬的 Docker 自动化工作流指南

发布人:慈云数据-客服中心 发布时间:12小时前 阅读量:0

Docker 工作流自动化教程|附完整命令

在现代软件开发中,Docker 已经成为开发、测试、部署环节中非常重要的基础工具。它可以帮助我们把应用程序及其依赖环境打包成镜像,并通过容器的方式在不同机器上稳定运行。相比传统部署方式,Docker 的优势在于环境一致、启动快速、易于迁移,并且非常适合与自动化脚本、CI/CD 平台结合,构建标准化的软件交付流程。

本文将围绕 Docker 工作流自动化 展开,介绍从项目容器化、镜像构建、容器运行、数据持久化、多服务编排,到自动化脚本与 CI/CD 集成的完整流程。文章中会附带大量可直接使用的命令,适合希望系统掌握 Docker 自动化工作流的开发者、测试人员、运维工程师阅读。


一、为什么要做 Docker 工作流自动化?

在没有 Docker 或自动化流程之前,一个项目从开发到上线通常会遇到以下问题:

  1. 环境不一致
    开发环境、测试环境、生产环境的软件版本不同,例如 Node.js、Java、MySQL、Redis 版本不一致,导致“我电脑上能运行”的问题频繁出现。

  2. 部署步骤复杂
    每次发布都需要手动拉代码、安装依赖、修改配置、启动服务,步骤多且容易出错。

  3. 回滚困难
    如果新版本发布失败,传统方式可能需要手动恢复代码、配置和依赖,风险较高。

  4. 多服务管理困难
    现代项目通常包含 Web 服务、数据库、缓存、消息队列等多个服务,手动管理启动顺序和网络配置成本较高。

  5. 缺少标准化交付流程
    不同成员的部署方式不同,难以形成可复制、可追踪、可审计的交付链路。

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_USERNAME
  • DOCKERHUB_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 自动化工作流可以设计为:

  1. 开发者提交代码到 Git 仓库;
  2. CI 平台自动拉取代码;
  3. CI 平台执行测试;
  4. 测试通过后构建 Docker 镜像;
  5. 使用 Git Commit ID 或版本号给镜像打标签;
  6. 推送镜像到镜像仓库;
  7. 服务器拉取指定版本镜像;
  8. 使用 Docker Compose 启动或更新服务;
  9. 检查容器健康状态;
  10. 如部署失败,快速回滚到旧版本镜像。

对应的核心命令可以概括为:

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 工作流更加稳定、安全、可维护,建议遵循以下实践:

  1. 不要在生产环境使用不确定的 latest 标签
    可以保留 latest,但生产发布最好使用明确版本号。

  2. 使用 .dockerignore 减少构建上下文
    避免把无关文件复制进镜像。

  3. 优先使用轻量基础镜像
    例如 Alpine、Slim 版本,但也要注意兼容性。

  4. 敏感配置不要写死在镜像中
    使用环境变量、密钥管理工具或 CI/CD Secret。

  5. 数据库数据必须挂载数据卷
    避免容器删除后数据丢失。

  6. 使用 Docker Compose 管理多服务项目
    比手写多个 docker run 命令更清晰、更容易维护。

  7. 部署前保留旧版本镜像
    出现问题时可以快速回滚。

  8. 定期清理无用资源
    防止磁盘被构建缓存和旧镜像占满。

  9. 为服务增加健康检查
    方便自动化平台判断服务是否正常。

  10. 将常用操作封装成脚本
    例如构建、推送、部署、回滚、清理等,提高效率并降低人为错误。


十八、完整命令清单

下面整理一份常用 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 自动化交付体系。

目录结构
全文