mirror of
https://github.com/yeasy/docker_practice.git
synced 2026-03-11 12:21:17 +00:00
Split chapter 20
This commit is contained in:
11
21_case_devops/README.md
Normal file
11
21_case_devops/README.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# 第二十一章 实战案例 - Devops
|
||||
|
||||
本章将介绍 Docker 在 DevOps 场景下的实战案例。
|
||||
|
||||
* [DevOps 完整工作流](devops_workflow.md)
|
||||
* [GitHub Actions](github_actions.md)
|
||||
* [Drone](drone.md)
|
||||
* [Drone Demo](drone_demo.md)
|
||||
* [在 IDE 中使用 Docker](ide.md)
|
||||
* [VS Code](vsCode.md)
|
||||
* [本章小结](summary.md)
|
||||
86
21_case_devops/devops_workflow.md
Normal file
86
21_case_devops/devops_workflow.md
Normal file
@@ -0,0 +1,86 @@
|
||||
# 21.1 DevOps 工作流完整示例
|
||||
|
||||
本章将演示一个基于 Docker、Kubernetes 和 Jenkins/GitLab CI 的完整 DevOps 工作流。
|
||||
|
||||
## 21.1.1 工作流概览
|
||||
|
||||
1. **Code**:开发人员提交代码到 GitLab。
|
||||
2. **Build**:GitLab CI 触发构建任务。
|
||||
3. **Test**:运行单元测试和集成测试。
|
||||
4. **Package**:构建 Docker 镜像并推送到 Harbor/Registry。
|
||||
5. **Deploy (Staging)**:自动部署到测试环境 Kubernetes 集群。
|
||||
6. **Verify**:人工或自动化验证。
|
||||
7. **Release (Production)**:审批后自动部署到生产环境。
|
||||
|
||||
## 21.1.2 关键配置示例
|
||||
|
||||
本节通过一组最小可用的片段,展示典型 DevOps 流程中与 Docker 相关的关键配置。
|
||||
|
||||
### 1. Dockerfile 多阶段构建
|
||||
|
||||
使用 Docker 多阶段构建可以有效减小镜像体积。
|
||||
|
||||
Dockerfile 内容如下:
|
||||
|
||||
```dockerfile
|
||||
## Build stage
|
||||
|
||||
FROM golang:1.18 AS builder
|
||||
WORKDIR /app
|
||||
COPY . .
|
||||
RUN go build -o main .
|
||||
|
||||
## Final stage
|
||||
|
||||
FROM alpine:latest
|
||||
WORKDIR /app
|
||||
COPY --from=builder /app/main .
|
||||
CMD ["./main"]
|
||||
```
|
||||
|
||||
### 2. GitLab CI 配置
|
||||
|
||||
GitLab CI(`.gitlab-ci.yml`)配置如下:
|
||||
|
||||
```yaml
|
||||
stages:
|
||||
- test
|
||||
- build
|
||||
- deploy
|
||||
|
||||
unit_test:
|
||||
stage: test
|
||||
image: golang:1.18
|
||||
script:
|
||||
- go test ./...
|
||||
|
||||
build_image:
|
||||
stage: build
|
||||
image: docker:20.10.16
|
||||
services:
|
||||
- docker:20.10.16-dind
|
||||
script:
|
||||
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD \
|
||||
$CI_REGISTRY
|
||||
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
|
||||
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
|
||||
|
||||
deploy_staging:
|
||||
stage: deploy
|
||||
image: dtzar/helm-kubectl
|
||||
script:
|
||||
- kubectl config set-cluster k8s --server=$KUBE_URL --insecure-skip-tls-verify=true
|
||||
- kubectl config set-credentials admin --token=$KUBE_TOKEN
|
||||
- kubectl config set-context default --cluster=k8s --user=admin
|
||||
- kubectl config use-context default
|
||||
- kubectl set image deployment/myapp myapp=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
|
||||
-n staging
|
||||
only:
|
||||
- develop
|
||||
```
|
||||
|
||||
## 21.1.3 最佳实践
|
||||
|
||||
1. **不可变基础设施**:一旦镜像构建完成,在各个环境(Dev、Staging、Prod)中都应该使用同一个镜像 tag(通常是 commit hash),而不是重新构建。
|
||||
2. **配置分离**:使用 ConfigMap 和 Secret 管理环境特定的配置,不要打包进镜像。
|
||||
3. **GitOps**:考虑引入 ArgoCD,将部署配置也作为代码存储在 Git 中,实现 Git 驱动的部署同步。
|
||||
102
21_case_devops/drone.md
Normal file
102
21_case_devops/drone.md
Normal file
@@ -0,0 +1,102 @@
|
||||
# 21.3 Drone
|
||||
|
||||
基于 `Docker` 的 `CI/CD` 工具 `Drone`,所有编译、测试的流程都在容器中进行。
|
||||
|
||||
开发者只需在项目中包含 `.drone.yml` 文件,将代码推送到 git 仓库,`Drone` 就能够自动化地进行编译、测试、发布。
|
||||
|
||||
本小节以 `GitHub` + `Drone` 来演示 `Drone` 的工作流程。
|
||||
当然在实际开发过程中,你的代码也许不在 GitHub 托管,那么你可以尝试使用 `Gogs` + `Drone` 来进行 CI/CD。
|
||||
|
||||
## 21.3.1 关联项目
|
||||
|
||||
在 GitHub 新建一个名为 `drone-demo` 的仓库。
|
||||
|
||||
打开我们已经部署好的 Drone 网站或者 [Drone Cloud](https://cloud.drone.io),
|
||||
使用 GitHub 账号登录,在界面中关联刚刚新建的 `drone-demo` 仓库。
|
||||
|
||||
## 21.3.2 编写项目源代码
|
||||
|
||||
初始化一个 git 仓库:
|
||||
|
||||
```bash
|
||||
mkdir drone-demo
|
||||
cd drone-demo
|
||||
|
||||
git init
|
||||
|
||||
git remote add origin git@github.com:username/drone-demo.git
|
||||
```
|
||||
|
||||
这里以一个简单的 `Go` 程序为例,该程序输出 `Hello World!`
|
||||
|
||||
编写 `app.go` 文件:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
fmt.Printf("Hello World!\n")
|
||||
}
|
||||
```
|
||||
|
||||
编写 `.drone.yml` 文件:
|
||||
|
||||
```yaml
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: build
|
||||
|
||||
steps:
|
||||
- name: build
|
||||
image: golang:alpine
|
||||
pull: if-not-exists
|
||||
environment:
|
||||
KEY: VALUE
|
||||
commands:
|
||||
- echo $KEY
|
||||
- pwd
|
||||
- ls
|
||||
- CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .
|
||||
- ./app
|
||||
|
||||
trigger:
|
||||
branch:
|
||||
- master
|
||||
```
|
||||
|
||||
现在目录结构如下:
|
||||
|
||||
```bash
|
||||
.
|
||||
├── .drone.yml
|
||||
└── app.go
|
||||
```
|
||||
|
||||
## 21.3.3 推送项目源代码到 GitHub
|
||||
|
||||
运行以下命令:
|
||||
|
||||
```bash
|
||||
git add .
|
||||
|
||||
git commit -m "test drone ci"
|
||||
|
||||
git push origin master
|
||||
```
|
||||
|
||||
## 21.3.4 查看项目构建过程及结果
|
||||
|
||||
打开我们部署好的 `Drone` 网站或者 Drone Cloud,即可看到构建结果。
|
||||
|
||||

|
||||
|
||||
当然我们也可以把构建结果上传到 GitHub、Docker Registry、
|
||||
云服务商提供的对象存储,或者生产环境中。
|
||||
|
||||
## 21.3.5 参考链接
|
||||
|
||||
* [Drone Github](https://github.com/drone/drone)
|
||||
* [Drone 文档](https://docs.drone.io/)
|
||||
* [Drone 示例](https://github.com/docker-practice/drone-demo)
|
||||
7
21_case_devops/drone_demo.app.go
Normal file
7
21_case_devops/drone_demo.app.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main(){
|
||||
fmt.Printf("Hello World!\n");
|
||||
}
|
||||
19
21_case_devops/drone_demo.drone.yml
Normal file
19
21_case_devops/drone_demo.drone.yml
Normal file
@@ -0,0 +1,19 @@
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: build
|
||||
steps:
|
||||
- name: build
|
||||
image: golang:alpine
|
||||
pull: if-not-exists # always never
|
||||
environment:
|
||||
KEY: VALUE
|
||||
commands:
|
||||
- echo $KEY
|
||||
- pwd
|
||||
- ls
|
||||
- CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .
|
||||
- ./app
|
||||
|
||||
trigger:
|
||||
branch:
|
||||
- master
|
||||
22
21_case_devops/drone_demo.md
Normal file
22
21_case_devops/drone_demo.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# 21.4 Drone Demo
|
||||
|
||||
## 21.4.1 Demo 项目说明
|
||||
|
||||
这是一个基于 Go 语言编写的简单 Web 应用示例,用于演示 Drone CI 的持续集成流程。
|
||||
|
||||
## 21.4.2 目录结构
|
||||
|
||||
* `drone_demo.app.go`:简单的 Go Web 服务器代码。
|
||||
* `drone_demo.drone.yml`:Drone CI 的配置文件,定义了构建和测试流程。
|
||||
|
||||
## 21.4.3 如何使用
|
||||
|
||||
1. 确保本地已安装 Docker 环境。
|
||||
2. 将示例文件重命名为 Drone 期望的文件名:
|
||||
|
||||
```bash
|
||||
cp drone_demo.app.go app.go
|
||||
cp drone_demo.drone.yml .drone.yml
|
||||
```
|
||||
|
||||
3. 将 `app.go` 与 `.drone.yml` 推送到你的 `drone-demo` 仓库,即可在 Drone 中看到构建结果。
|
||||
38
21_case_devops/drone_docker-compose.yml
Normal file
38
21_case_devops/drone_docker-compose.yml
Normal file
@@ -0,0 +1,38 @@
|
||||
|
||||
|
||||
services:
|
||||
|
||||
drone-server:
|
||||
image: drone/drone:2.3.1
|
||||
ports:
|
||||
- 443:443
|
||||
- 80:80
|
||||
volumes:
|
||||
- drone-data:/data:rw
|
||||
- ./ssl:/etc/certs
|
||||
restart: always
|
||||
environment:
|
||||
- DRONE_SERVER_HOST=${DRONE_SERVER_HOST:-drone.domain.com}
|
||||
- DRONE_SERVER_PROTO=${DRONE_SERVER_PROTO:-https}
|
||||
- DRONE_RPC_SECRET=${DRONE_RPC_SECRET:-secret}
|
||||
- DRONE_GITHUB_SERVER=https://github.com
|
||||
- DRONE_GITHUB_CLIENT_ID=${DRONE_GITHUB_CLIENT_ID}
|
||||
- DRONE_GITHUB_CLIENT_SECRET=${DRONE_GITHUB_CLIENT_SECRET}
|
||||
|
||||
drone-agent:
|
||||
image: drone/drone-runner-docker:1
|
||||
restart: always
|
||||
depends_on:
|
||||
- drone-server
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:rw
|
||||
environment:
|
||||
- DRONE_RPC_PROTO=http
|
||||
- DRONE_RPC_HOST=drone-server
|
||||
- DRONE_RPC_SECRET=${DRONE_RPC_SECRET:-secret}
|
||||
- DRONE_RUNNER_NAME=${HOSTNAME:-demo}
|
||||
- DRONE_RUNNER_CAPACITY=2
|
||||
dns: 114.114.114.114
|
||||
|
||||
volumes:
|
||||
drone-data:
|
||||
6
21_case_devops/drone_env.example
Normal file
6
21_case_devops/drone_env.example
Normal file
@@ -0,0 +1,6 @@
|
||||
DRONE_SERVER_HOST=
|
||||
DRONE_SERVER_PROTO=
|
||||
DRONE_RPC_SECRET=
|
||||
HOSTNAME=
|
||||
DRONE_GITHUB_CLIENT_ID=
|
||||
DRONE_GITHUB_CLIENT_SECRET=
|
||||
2
21_case_devops/drone_gitignore
Normal file
2
21_case_devops/drone_gitignore
Normal file
@@ -0,0 +1,2 @@
|
||||
.env
|
||||
ssl/*
|
||||
53
21_case_devops/github_actions.md
Normal file
53
21_case_devops/github_actions.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# 21.2 GitHub Actions
|
||||
|
||||
GitHub [Actions](https://github.com/features/actions) 是 GitHub 推出的一款 CI/CD 工具。
|
||||
|
||||
我们可以在每个 `job` 的 `step` 中使用 Docker 执行构建步骤。
|
||||
|
||||
## 21.2.1 最小可用示例
|
||||
|
||||
在仓库根目录创建 `/.github/workflows/ci.yml`:
|
||||
|
||||
```yaml
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: docker/setup-buildx-action@v3
|
||||
- uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
push: false
|
||||
tags: local/test:ci
|
||||
```
|
||||
|
||||
该示例会在 GitHub Actions 中构建当前仓库的 Docker 镜像(不推送到 registry)。
|
||||
|
||||
## 21.2.2 最佳实践
|
||||
|
||||
* 固定 action 的主版本(例如 `@v4` / `@v6`),避免使用 `@master` 这类浮动引用。
|
||||
* 设置最小权限(例如 `contents: read`),需要写入权限时再打开。
|
||||
* 需要依赖缓存时,优先使用官方支持的缓存方案(例如针对语言包管理器的 cache 或 BuildKit cache)。
|
||||
|
||||
如果你需要在某个步骤里直接运行容器镜像(而不是构建镜像),可以使用 `docker://` 语法:
|
||||
|
||||
```yaml
|
||||
- name: Run container step
|
||||
uses: docker://golang:alpine
|
||||
with:
|
||||
args: go version
|
||||
```
|
||||
|
||||
## 21.2.3 参考资料
|
||||
|
||||
* [Actions Docs](https://docs.github.com/en/actions)
|
||||
53
21_case_devops/ide.md
Normal file
53
21_case_devops/ide.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# 21.5 在 IDE 中使用 Docker
|
||||
|
||||
使用 IDE 进行开发,往往要求本地安装好工具链。一些 IDE 支持 Docker 容器中的工具链,这样充分利用了 Docker 的优点,而无需在本地安装。
|
||||
|
||||
本节关注一个核心目标:**把“开发依赖”放进容器,把“源码编辑体验”留在本地 IDE**。
|
||||
|
||||
## 21.5.1 适用场景
|
||||
|
||||
* 团队希望统一开发环境(Go/Node/Python 版本、系统依赖、编译链)。
|
||||
* 本地系统不方便安装依赖(例如 Windows、公司管控环境)。
|
||||
* 项目依赖较重(例如需要 `gcc`、数据库客户端、特定系统库)。
|
||||
|
||||
不太适合的场景:强依赖本机 GPU/USB 设备、或需要非常低延迟文件 IO 的工程(此时可能需要额外调优挂载/同步策略)。
|
||||
|
||||
## 21.5.2 最小可用模式:docker compose + 开发容器
|
||||
|
||||
下面用一个“长期运行的开发容器”作为例子(以 Go 为例,你可以替换为 Node/Python)。
|
||||
|
||||
1. 在项目中创建 `compose.yaml`(或复用你已有的 compose 文件):
|
||||
|
||||
```yaml
|
||||
services:
|
||||
dev:
|
||||
image: golang:1.22
|
||||
working_dir: /work
|
||||
volumes:
|
||||
- ./:/work
|
||||
command: sleep infinity
|
||||
```
|
||||
|
||||
1. 启动开发容器:
|
||||
|
||||
```bash
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
1. 进入容器安装依赖/执行命令:
|
||||
|
||||
```bash
|
||||
docker compose exec dev bash
|
||||
go version
|
||||
go test ./...
|
||||
```
|
||||
|
||||
这个模式的优点是“简单直接、IDE 无关”,缺点是 IDE 需要额外配置
|
||||
(例如配置远程解释器/语言服务,或使用 VS Code Dev Containers)。
|
||||
|
||||
## 21.5.3 目录挂载与权限建议
|
||||
|
||||
* Linux 下如果遇到容器内写文件权限问题,优先确保容器内用户与宿主机 UID/GID 对齐。
|
||||
VS Code Dev Containers 支持自动处理;手写 Dockerfile/compose 时也可以显式设置用户。
|
||||
* 如果遇到文件变更监听不生效(常见于 macOS/Windows 的虚拟化文件系统),
|
||||
优先使用语言/工具支持的轮询模式或提高 watcher 限制。
|
||||
16
21_case_devops/summary.md
Normal file
16
21_case_devops/summary.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# 21.7 本章小结
|
||||
|
||||
本章通过一个完整的 DevOps 工作流示例,串联了从代码提交、自动化测试、镜像构建、
|
||||
到部署发布的一整套实践路径。
|
||||
|
||||
在落地时,建议重点把握以下原则:
|
||||
|
||||
* **不可变交付物**:同一份产物(镜像)在不同环境中流转,使用 commit hash 等方式标识版本。
|
||||
* **最小权限与密钥管理**:CI 平台权限尽量收敛,敏感信息使用 Secret 管理并定期轮换。
|
||||
* **流水线可观测与可回滚**:为关键步骤保留日志与制品,发布失败时能快速定位并回滚。
|
||||
* **开发环境一致性**:通过 Dev Containers / compose 开发容器减少“在我电脑上可以”的问题。
|
||||
|
||||
下一步你可以根据团队现状选择一条主线深入:
|
||||
|
||||
* 已在用 GitHub:优先补全 Actions 的缓存、制品、发布策略。
|
||||
* 自建体系:结合私有 Registry、Kubernetes 与 GitOps 工具完善部署与审计。
|
||||
62
21_case_devops/vsCode.md
Normal file
62
21_case_devops/vsCode.md
Normal file
@@ -0,0 +1,62 @@
|
||||
# 21.6 VS Code 中使用 Docker
|
||||
|
||||
VS Code 的 [Dev Containers](https://code.visualstudio.com/docs/devcontainers/containers)
|
||||
可以把“开发环境”放进容器,同时保留 VS Code 的编辑、补全、调试体验。
|
||||
|
||||
本节提供一个最小可用示例:把任意项目(以 Go 为例)变成“打开即开发”的容器化环境。
|
||||
|
||||
## 21.6.1 前置条件
|
||||
|
||||
* 安装 Docker Desktop(或 Linux 上的 Docker Engine)。
|
||||
* VS Code 安装扩展:Dev Containers(`ms-vscode-remote.remote-containers`)。
|
||||
|
||||
## 21.6.2 最小示例:.devcontainer/devcontainer.json
|
||||
|
||||
在项目根目录创建 `.devcontainer/devcontainer.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "docker-practice-dev",
|
||||
"image": "golang:1.22",
|
||||
"workspaceFolder": "/work",
|
||||
"workspaceMount": "source=${localWorkspaceFolder},target=/work,type=bind",
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
"golang.Go"
|
||||
]
|
||||
}
|
||||
},
|
||||
"postCreateCommand": "go version"
|
||||
}
|
||||
```
|
||||
|
||||
然后在 VS Code 命令面板选择:
|
||||
|
||||
* `Dev Containers: Reopen in Container`
|
||||
|
||||
VS Code 会拉取镜像并启动容器,随后你就可以在容器内运行:
|
||||
|
||||
```bash
|
||||
go test ./...
|
||||
```
|
||||
|
||||
## 21.6.3 结合 Docker Compose(可选)
|
||||
|
||||
如果项目同时依赖数据库/缓存(例如 Postgres/Redis),可以使用 `dockerComposeFile`
|
||||
把依赖一起拉起。
|
||||
|
||||
示例(`devcontainer.json` 片段):
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "compose-dev",
|
||||
"dockerComposeFile": [
|
||||
"../docker-compose.yml"
|
||||
],
|
||||
"service": "dev",
|
||||
"workspaceFolder": "/work"
|
||||
}
|
||||
```
|
||||
|
||||
注意:`service` 需要对应 compose 里的服务名。
|
||||
Reference in New Issue
Block a user