Go工程師體系課 015

Docker 容器化 —— Go 項目實戰指南


一、Docker 核心概念

1.1 什麼是 Docker

Docker 是一個開源的容器化平臺,它可以將應用程序及其所有依賴項打包到一個標準化的單元(容器)中,從而實現"一次構建,到處運行"。對於 Go 開發者而言,Docker 解決了以下痛點:

  • 開發環境與生產環境不一致
  • 依賴管理複雜(數據庫、緩存、消息隊列等中間件)
  • 部署流程不標準化
  • 微服務架構下多服務協同困難

1.2 三大核心概念

鏡像(Image)

鏡像是一個只讀模板,包含了運行應用所需的所有文件系統層。可以類比爲"類"(Class):

  • 鏡像由多層(Layer)組成,每一層代表 Dockerfile 中的一條指令
  • 層是隻讀的、可複用的,多個鏡像可以共享底層
  • 鏡像通過 tag 進行版本管理,如 golang:1.22-alpine
+---------------------------+
|   應用代碼層 (COPY .)      |  <-- 最上層,變化最頻繁
+---------------------------+
|   依賴安裝層 (go mod)      |
+---------------------------+
|   基礎工具層 (RUN apk)     |
+---------------------------+
|   基礎鏡像層 (alpine)      |  <-- 最底層,最穩定
+---------------------------+

容器(Container)

容器是鏡像的運行實例,可以類比爲"對象"(Object):

  • 容器在鏡像之上添加了一個可寫層
  • 每個容器都有自己獨立的文件系統、網絡、進程空間
  • 容器是臨時的、無狀態的,銷燬後可寫層的數據會丟失
  • 需要持久化的數據應使用數據卷(Volume)

倉庫(Registry)

倉庫是存儲和分發鏡像的服務:

  • Docker Hub:官方公共倉庫,類似 GitHub
  • 私有倉庫:如 Harbor、AWS ECR、阿里雲 ACR
  • 鏡像通過 registry/repository:tag 的格式標識,如 docker.io/library/golang:1.22

二、Dockerfile 編寫(以 Go 項目爲例)

2.1 基礎 Dockerfile

假設我們有一個簡單的 Go Web 服務:

// main.go
package main

import (
    "fmt"
    "log"
    "net/http"
    "os"
)

func main() {
    port := os.Getenv("PORT")
    if port == "" {
        port = "8080"
    }

    http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
        w.WriteHeader(http.StatusOK)
        fmt.Fprintf(w, "OK")
    })

    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hello from Go Docker Service!")
    })

    log.Printf("Server starting on port %s", port)
    log.Fatal(http.ListenAndServe(":"+port, nil))
}

最簡單但不推薦的 Dockerfile:

# 不推薦:鏡像體積大,包含編譯工具鏈
FROM golang:1.22

WORKDIR /app
COPY . .
RUN go build -o server .

EXPOSE 8080
CMD ["./server"]

這種方式生成的鏡像通常超過 800MB,因爲包含了完整的 Go 編譯工具鏈。

2.2 多階段構建(Multi-stage Build)

多階段構建是 Go 項目 Docker 化的核心技巧,可以將鏡像從 800MB+ 縮減到 10-20MB:

# ============ 第一階段:編譯 ============
FROM golang:1.22-alpine AS builder

# 設置 Go 模塊代理(國內加速)
ENV GOPROXY=https://goproxy.cn,direct

WORKDIR /app

# 先複製依賴文件,利用緩存層(詳見 2.3 節)
COPY go.mod go.sum ./
RUN go mod download

# 複製源代碼並編譯
COPY . .

# CGO_ENABLED=0 生成靜態鏈接的二進制文件
# -ldflags="-s -w" 去除調試信息,減小體積
RUN CGO_ENABLED=0 GOOS=linux go build \
    -ldflags="-s -w" \
    -o /app/server .

# ============ 第二階段:運行 ============
FROM alpine:3.19

# 安裝必要的 CA 證書(HTTPS 請求需要)和時區數據
RUN apk --no-cache add ca-certificates tzdata

# 創建非 root 用戶
RUN addgroup -S appgroup && adduser -S appuser -G appgroup

WORKDIR /app

# 從 builder 階段複製編譯好的二進制文件
COPY --from=builder /app/server .

# 複製配置文件(如果有)
# COPY --from=builder /app/config ./config

# 切換到非 root 用戶
USER appuser

EXPOSE 8080

# 使用 ENTRYPOINT 而非 CMD,防止被意外覆蓋
ENTRYPOINT ["./server"]

更極致的方案 -- 使用 scratch 空鏡像:

# 編譯階段同上...

# 使用空鏡像,最終鏡像僅包含二進制文件
FROM scratch

# 從 builder 複製 CA 證書
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/

# 從 builder 複製時區信息
COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo

COPY --from=builder /app/server /server

EXPOSE 8080
ENTRYPOINT ["/server"]

鏡像體積對比:

基礎鏡像 最終大小 適用場景
golang:1.22 ~850MB 不推薦用於生產
alpine:3.19 ~15MB 推薦,支持 shell 調試
scratch ~8MB 極致精簡,無 shell
distroless ~12MB Google 推薦,安全性好

2.3 構建緩存優化

Docker 構建時,每一層都會被緩存。只要某一層的輸入沒有變化,就會複用緩存。關鍵原則是:把變化頻率低的層放在前面,變化頻率高的層放在後面。

# 好的做法:分離依賴下載和代碼編譯
COPY go.mod go.sum ./       # 依賴文件變化少,緩存命中率高
RUN go mod download          # 只有依賴變化時才重新下載
COPY . .                     # 代碼頻繁變化
RUN go build -o server .     # 每次代碼變化都重新編譯

# 壞的做法:一次性複製所有文件
COPY . .                     # 任何文件變化都導致後續所有層緩存失效
RUN go mod download
RUN go build -o server .

2.4 最佳實踐總結

.dockerignore 文件

在項目根目錄創建 .dockerignore,減少構建上下文大小:

# .dockerignore
.git
.gitignore
.idea
.vscode
*.md
README*
LICENSE
Makefile
docker-compose*.yml
Dockerfile*
tmp/
vendor/
bin/
*.test
*.prof

安全性最佳實踐

# 1. 使用特定版本標籤,避免用 latest
FROM alpine:3.19    # 好
FROM alpine:latest  # 壞 -- 不可復現

# 2. 以非 root 用戶運行
RUN addgroup -S app && adduser -S app -G app
USER app

# 3. 只讀文件系統(運行時指定)
# docker run --read-only --tmpfs /tmp myapp

# 4. 不要在鏡像中存儲密鑰
# 壞的做法
ENV DB_PASSWORD=secret123
# 好的做法:運行時通過環境變量或 Secret 管理工具注入

三、docker-compose 編排

3.1 爲什麼需要 docker-compose

在微服務架構中,一個 Go 項目通常依賴多個外部服務。docker-compose 允許用一個 YAML 文件定義和管理多個容器的編排。

3.2 完整示例:Go 服務 + MySQL + Redis + Consul

# docker-compose.yml
version: "3.9"

services:
  # ============ Go 應用服務 ============
  app:
    build:
      context: .
      dockerfile: Dockerfile
      args:
        - GOPROXY=https://goproxy.cn,direct
    container_name: go-app
    ports:
      - "8080:8080"    # 主機端口:容器端口
    environment:
      - PORT=8080
      - DB_HOST=mysql
      - DB_PORT=3306
      - DB_USER=root
      - DB_PASSWORD=rootpassword
      - DB_NAME=myapp
      - REDIS_ADDR=redis:6379
      - CONSUL_ADDR=consul:8500
    depends_on:
      mysql:
        condition: service_healthy
      redis:
        condition: service_healthy
      consul:
        condition: service_started
    networks:
      - app-network
    restart: unless-stopped
    # 資源限制
    deploy:
      resources:
        limits:
          cpus: "1.0"
          memory: 512M
        reservations:
          cpus: "0.25"
          memory: 128M

  # ============ MySQL 數據庫 ============
  mysql:
    image: mysql:8.0
    container_name: go-mysql
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: rootpassword
      MYSQL_DATABASE: myapp
      MYSQL_CHARSET: utf8mb4
    volumes:
      - mysql-data:/var/lib/mysql              # 數據持久化
      - ./deploy/mysql/init.sql:/docker-entrypoint-initdb.d/init.sql  # 初始化腳本
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - app-network
    restart: unless-stopped

  # ============ Redis 緩存 ============
  redis:
    image: redis:7-alpine
    container_name: go-redis
    ports:
      - "6379:6379"
    command: redis-server --requirepass redispassword --appendonly yes
    volumes:
      - redis-data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "-a", "redispassword", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - app-network
    restart: unless-stopped

  # ============ Consul 服務註冊與發現 ============
  consul:
    image: hashicorp/consul:1.17
    container_name: go-consul
    ports:
      - "8500:8500"    # HTTP API 和 Web UI
      - "8600:8600/udp" # DNS
    command: agent -server -bootstrap-expect=1 -ui -client=0.0.0.0
    volumes:
      - consul-data:/consul/data
    networks:
      - app-network
    restart: unless-stopped

# ============ 數據卷定義 ============
volumes:
  mysql-data:
    driver: local
  redis-data:
    driver: local
  consul-data:
    driver: local

# ============ 網絡定義 ============
networks:
  app-network:
    driver: bridge

3.3 常用 docker-compose 命令

# 啓動所有服務(後臺運行)
docker-compose up -d

# 啓動並重新構建鏡像
docker-compose up -d --build

# 查看服務狀態
docker-compose ps

# 查看某個服務的日誌
docker-compose logs -f app

# 停止所有服務
docker-compose down

# 停止並刪除數據卷(慎用,會丟失數據)
docker-compose down -v

# 只啓動某個服務及其依賴
docker-compose up -d app

# 進入某個服務的容器
docker-compose exec app sh

# 擴展服務實例數
docker-compose up -d --scale app=3

四、常用 Docker 命令速查

4.1 鏡像管理

# 構建鏡像
docker build -t myapp:v1.0 .
docker build -t myapp:v1.0 -f deploy/Dockerfile .   # 指定 Dockerfile 路徑

# 查看本地鏡像
docker images
docker image ls

# 刪除鏡像
docker rmi myapp:v1.0
docker image prune           # 清理懸空鏡像(dangling images)
docker image prune -a        # 清理所有未使用的鏡像

# 鏡像標籤
docker tag myapp:v1.0 registry.example.com/myapp:v1.0

# 導入導出(離線場景)
docker save -o myapp.tar myapp:v1.0
docker load -i myapp.tar

# 查看鏡像構建歷史 / 層信息
docker history myapp:v1.0
docker inspect myapp:v1.0

4.2 容器管理

# 運行容器
docker run -d --name myapp -p 8080:8080 myapp:v1.0
docker run -d --name myapp \
  -p 8080:8080 \
  -e DB_HOST=localhost \
  -v /host/data:/app/data \
  --restart unless-stopped \
  myapp:v1.0

# 查看運行中的容器
docker ps
docker ps -a                 # 包含已停止的容器

# 容器生命週期
docker start myapp
docker stop myapp
docker restart myapp
docker rm myapp              # 刪除已停止的容器
docker rm -f myapp           # 強制刪除(包括運行中的)

# 進入容器內部
docker exec -it myapp sh     # alpine 用 sh
docker exec -it myapp bash   # 帶 bash 的鏡像用 bash

# 查看日誌
docker logs myapp
docker logs -f myapp         # 實時跟蹤
docker logs --tail 100 myapp # 最後100行

# 查看容器資源使用
docker stats
docker stats myapp

# 複製文件
docker cp myapp:/app/logs/app.log ./app.log   # 容器到主機
docker cp ./config.yaml myapp:/app/config.yaml # 主機到容器

4.3 系統清理

# 一鍵清理:停止的容器、懸空鏡像、未使用的網絡
docker system prune

# 包含未使用的數據卷(慎用)
docker system prune --volumes

# 查看 Docker 磁盤使用情況
docker system df

五、Docker 網絡模式

5.1 bridge 模式(默認)

每個容器擁有獨立的網絡命名空間,通過虛擬網橋 docker0 進行通信:

# 創建自定義 bridge 網絡
docker network create my-network

# 將容器連接到自定義網絡
docker run -d --name app --network my-network myapp:v1.0
docker run -d --name db --network my-network mysql:8.0

# 同一網絡內的容器可以通過容器名互相訪問
# app 容器內可以用 "db:3306" 連接數據庫

自定義 bridge 網絡的優勢:
- 容器間通過名稱(DNS)互相發現
- 更好的網絡隔離
- 可以動態連接/斷開容器

5.2 host 模式

容器直接使用宿主機的網絡,沒有網絡隔離:

docker run -d --network host myapp:v1.0
# 容器中監聽 8080 端口 = 宿主機 8080 端口
# 不需要 -p 端口映射
  • 優點:性能最好,沒有 NAT 開銷
  • 缺點:端口衝突風險,安全性較低
  • 適用場景:高性能網絡需求、網絡調試

5.3 none 模式

容器沒有網絡連接,完全隔離:

docker run -d --network none myapp:v1.0
  • 適用場景:只需要進行計算、不需要網絡的任務

5.4 網絡模式對比

模式 隔離性 性能 使用場景
bridge 默認選擇,大部分場景
host 高性能需求
none 完全 - 安全敏感的計算任務
overlay 跨主機的 Swarm/K8s

六、數據卷(Volume)與持久化

6.1 爲什麼需要數據卷

容器的文件系統是臨時的,容器被刪除後數據就會丟失。數據卷提供了持久化存儲機制。

6.2 三種掛載方式

# 1. 命名卷(Named Volume)-- 推薦用於數據持久化
docker volume create mydata
docker run -v mydata:/app/data myapp:v1.0

# 2. 綁定掛載(Bind Mount)-- 適合開發時掛載源代碼
docker run -v /host/path:/container/path myapp:v1.0
docker run -v $(pwd)/config:/app/config:ro myapp:v1.0   # 只讀掛載

# 3. tmpfs 掛載 -- 內存中的臨時文件系統
docker run --tmpfs /app/tmp myapp:v1.0

6.3 數據卷管理

# 查看所有卷
docker volume ls

# 查看卷詳情
docker volume inspect mydata

# 刪除卷
docker volume rm mydata

# 清理未使用的卷
docker volume prune

6.4 在 Go 項目中的典型用法

# docker-compose.yml 中的卷使用
services:
  app:
    volumes:
      - ./config:/app/config:ro    # 配置文件(只讀綁定)
      - app-logs:/app/logs         # 日誌目錄(命名卷)
      - /app/tmp                   # 匿名卷(臨時文件)

  mysql:
    volumes:
      - mysql-data:/var/lib/mysql  # 數據庫數據(命名卷,最重要)

volumes:
  app-logs:
  mysql-data:

七、Docker 在微服務開發中的應用

7.1 本地開發工作流

在微服務架構下,一個 Go 服務可能依賴多個其他服務。Docker 讓本地開發變得輕鬆:

+-----------------------------------------------+
|           docker-compose 編排                  |
|                                               |
|  +----------+  +----------+  +----------+    |
|  | 用戶服務  |  | 訂單服務  |  | 商品服務  |    |
|  | Go :8081 |  | Go :8082 |  | Go :8083 |    |
|  +----+-----+  +----+-----+  +----+-----+    |
|       |              |              |          |
|  +----+--------------+--------------+----+    |
|  |          app-network (bridge)         |    |
|  +----+----------+----------+-----------+    |
|       |          |          |                 |
|  +----+---+ +---+----+ +--+------+           |
|  | MySQL  | | Redis  | | Consul  |           |
|  | :3306  | | :6379  | | :8500   |           |
|  +--------+ +--------+ +---------+           |
+-----------------------------------------------+

7.2 熱重載開發模式

開發時可以結合 air 等工具實現代碼熱重載:

# docker-compose.dev.yml
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile.dev
    volumes:
      - .:/app                  # 掛載源代碼
    command: air                 # 使用 air 熱重載
    ports:
      - "8080:8080"
# Dockerfile.dev
FROM golang:1.22-alpine

RUN go install github.com/air-verse/air@latest

WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download

# 不需要 COPY . . 因爲源代碼通過 volume 掛載
CMD ["air"]

7.3 集成測試

使用 Docker 可以輕鬆搭建集成測試環境:

# 啓動測試依賴
docker-compose -f docker-compose.test.yml up -d

# 運行集成測試
go test ./... -tags=integration

# 清理
docker-compose -f docker-compose.test.yml down -v

也可以在 Go 代碼中使用 testcontainers-go 庫動態創建測試容器:

package repository_test

import (
    "context"
    "testing"

    "github.com/testcontainers/testcontainers-go"
    "github.com/testcontainers/testcontainers-go/modules/mysql"
)

func TestUserRepository(t *testing.T) {
    ctx := context.Background()

    // 動態創建 MySQL 容器用於測試
    mysqlC, err := mysql.Run(ctx,
        "mysql:8.0",
        mysql.WithDatabase("testdb"),
        mysql.WithUsername("test"),
        mysql.WithPassword("test"),
    )
    if err != nil {
        t.Fatal(err)
    }
    defer mysqlC.Terminate(ctx)

    // 獲取連接地址
    host, _ := mysqlC.Host(ctx)
    port, _ := mysqlC.MappedPort(ctx, "3306")

    // 使用真實數據庫進行測試...
    t.Logf("MySQL running at %s:%s", host, port.Port())
}

八、鏡像推送到 Registry

8.1 推送到 Docker Hub

# 1. 登錄
docker login

# 2. 給鏡像打標籤(格式:用戶名/倉庫名:標籤)
docker tag myapp:v1.0 username/myapp:v1.0
docker tag myapp:v1.0 username/myapp:latest

# 3. 推送
docker push username/myapp:v1.0
docker push username/myapp:latest

8.2 推送到私有倉庫

# 以阿里雲 ACR 爲例
# 1. 登錄私有倉庫
docker login registry.cn-hangzhou.aliyuncs.com

# 2. 打標籤
docker tag myapp:v1.0 registry.cn-hangzhou.aliyuncs.com/myns/myapp:v1.0

# 3. 推送
docker push registry.cn-hangzhou.aliyuncs.com/myns/myapp:v1.0

8.3 搭建本地私有倉庫(Harbor)

Harbor 是企業級的 Docker 鏡像倉庫,支持權限管理、鏡像掃描等功能:

# 使用 Docker Compose 快速部署 Harbor
# 下載離線安裝包後:
./install.sh --with-chartmuseum --with-trivy

# 推送到 Harbor
docker tag myapp:v1.0 harbor.example.com/myproject/myapp:v1.0
docker push harbor.example.com/myproject/myapp:v1.0

8.4 CI/CD 中的自動構建與推送

在 GitHub Actions 中自動構建並推送鏡像:

# .github/workflows/docker.yml
name: Build and Push Docker Image

on:
  push:
    tags:
      - 'v*'

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: |
            username/myapp:${{ github.ref_name }}
            username/myapp:latest

九、Go 項目 Docker 化完整實戰流程

9.1 項目結構

myapp/
├── cmd/
│   └── server/
│       └── main.go          # 入口
├── internal/
│   ├── handler/             # HTTP 處理器
│   ├── service/             # 業務邏輯
│   ├── repository/          # 數據訪問
│   └── config/              # 配置管理
├── deploy/
│   ├── mysql/
│   │   └── init.sql         # 數據庫初始化
│   └── nginx/
│       └── nginx.conf       # 反向代理配置
├── go.mod
├── go.sum
├── Dockerfile
├── docker-compose.yml
├── docker-compose.dev.yml
├── .dockerignore
└── Makefile

9.2 Makefile 自動化

# Makefile
APP_NAME=myapp
VERSION=$(shell git describe --tags --always --dirty)
REGISTRY=registry.example.com/myns

.PHONY: build run test docker-build docker-push deploy clean

# 本地編譯
build:
    CGO_ENABLED=0 go build -ldflags="-s -w -X main.Version=$(VERSION)" \
        -o bin/$(APP_NAME) ./cmd/server

# 本地運行
run:
    go run ./cmd/server

# 運行測試
test:
    go test ./... -v -cover

# 構建 Docker 鏡像
docker-build:
    docker build -t $(APP_NAME):$(VERSION) .
    docker tag $(APP_NAME):$(VERSION) $(APP_NAME):latest

# 推送鏡像
docker-push: docker-build
    docker tag $(APP_NAME):$(VERSION) $(REGISTRY)/$(APP_NAME):$(VERSION)
    docker push $(REGISTRY)/$(APP_NAME):$(VERSION)

# 啓動開發環境
dev:
    docker-compose -f docker-compose.dev.yml up -d --build

# 啓動生產環境
deploy:
    docker-compose up -d --build

# 查看日誌
logs:
    docker-compose logs -f app

# 清理
clean:
    docker-compose down -v
    docker image prune -f
    rm -rf bin/

9.3 完整的生產級 Dockerfile

# ============ 第一階段:編譯 ============
FROM golang:1.22-alpine AS builder

# 安裝必要的構建工具
RUN apk add --no-cache git ca-certificates tzdata

# 設置 Go 環境
ENV GOPROXY=https://goproxy.cn,direct
ENV CGO_ENABLED=0
ENV GOOS=linux
ENV GOARCH=amd64

WORKDIR /build

# 依賴緩存層
COPY go.mod go.sum ./
RUN go mod download && go mod verify

# 編譯
COPY . .
ARG VERSION=dev
RUN go build \
    -ldflags="-s -w -X main.Version=${VERSION}" \
    -o /build/app \
    ./cmd/server

# ============ 第二階段:運行 ============
FROM alpine:3.19

LABEL maintainer="your-email@example.com"
LABEL version="${VERSION}"
LABEL description="My Go Application"

# 安裝運行時依賴
RUN apk --no-cache add ca-certificates tzdata && \
    cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
    echo "Asia/Shanghai" > /etc/timezone

# 創建非 root 用戶和必要目錄
RUN addgroup -S app && adduser -S app -G app && \
    mkdir -p /app/logs /app/config && \
    chown -R app:app /app

WORKDIR /app

# 複製二進制文件
COPY --from=builder /build/app .

# 複製配置文件模板(可選)
# COPY --from=builder /build/config ./config

# 切換到非 root 用戶
USER app

# 暴露端口
EXPOSE 8080

# 健康檢查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
    CMD wget --no-verbose --tries=1 --spider http://localhost:8080/health || exit 1

# 啓動
ENTRYPOINT ["./app"]

9.4 完整流程總結

# 1. 編寫代碼和 Dockerfile
# 2. 本地開發和測試
make dev              # 啓動開發環境
make test             # 運行測試

# 3. 構建鏡像
make docker-build     # 構建生產鏡像

# 4. 本地驗證
make deploy           # 啓動完整環境
make logs             # 查看日誌
curl http://localhost:8080/health  # 測試接口

# 5. 推送鏡像
make docker-push      # 推送到倉庫

# 6. 部署到服務器
ssh your-server
docker pull registry.example.com/myns/myapp:v1.0
docker-compose up -d

# 7. 清理
make clean

十、常見問題與排查

10.1 常見問題

問題 原因 解決方案
鏡像體積過大 未使用多階段構建 使用 multi-stage build
構建慢 緩存未命中 先 COPY go.mod,再 COPY .
容器內時區不對 缺少時區數據 安裝 tzdata,設置 TZ
HTTPS 請求失敗 缺少 CA 證書 apk add ca-certificates
無法連接其他容器 網絡不通 確保在同一 docker network
數據丟失 未使用 volume 重要數據用 named volume

10.2 調試技巧

# 查看容器內部文件系統
docker exec -it myapp sh

# 查看容器網絡配置
docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' myapp

# 查看容器環境變量
docker exec myapp env

# 臨時運行一個調試容器(和目標容器共享網絡)
docker run -it --rm --network container:myapp alpine sh

# 查看 Docker 構建過程(詳細輸出)
docker build --progress=plain -t myapp . 2>&1 | tee build.log

下一篇016 - Kubernetes 入門,學習如何將 Docker 容器部署到 K8s 集羣中進行生產級編排和管理。

主題測試文章,只做測試使用。發佈者:Walker,轉轉請注明出處:https://walker-learn.xyz/archives/6762

(0)
Walker的頭像Walker
上一篇 2小時前
下一篇 4小時前

相關推薦

  • Go工程師體系課 004

    需求分析 後臺管理系統 商品管理 商品列表 商品分類 品牌管理 品牌分類 訂單管理 訂單列表 用戶信息管理 用戶列表 用戶地址 用戶留言 輪播圖管理 電商系統 登錄頁面 首頁 商品搜索 商品分類導航 輪播圖展示 推薦商品展示 商品詳情頁 商品圖片展示 商品描述 商品規格選擇 加入購物車 購物車 商品列表 數量調整 刪除商品 結算功能 用戶中心 訂單中心 我的…

    14小時前
    400
  • Go工程師體系課 002

    GOPATH 與 Go Modules 的區別 1. 概念 GOPATH 是 Go 的早期依賴管理機制。 所有的 Go 項目和依賴包必須放在 GOPATH 目錄中(默認是 ~/go)。 一定要設置 GO111MODULE=off 項目路徑必須按照 src/包名 的結構組織。 不支持版本控制,依賴管理需要手動處理(例如 go get)。 查找依賴包的順序是 g…

    1天前
    400
  • Go工程師體系課 009

    其它一些功能 個人中心 收藏 管理收貨地址(增刪改查) 留言 拷貝inventory_srv--> userop_srv 查詢替換所有的inventory Elasticsearch 深度解析文檔 1. 什麼是Elasticsearch Elasticsearch是一個基於Apache Lucene構建的分佈式、RESTful搜索和分析引擎,能夠快速地…

    後端開發 9小時前
    400
  • Go工程師體系課 018

    API 網關與持續部署入門(Kong & Jenkins) 對應資料目錄《第 2 章 Jenkins 入門》《第 3 章 通過 Jenkins 部署服務》,整理 Kong 與 Jenkins 在企業級持續交付中的實戰路徑。即便零基礎,也能順著步驟搭建出自己的網關 + 持續部署流水線。 課前導覽:什麼是 API 網關 API 網關位於客戶端與後端微服務…

    後端開發 27分鐘前
    000
  • Go工程師體系課 006

    項目結構說明:user-web 模塊 user-web 是 joyshop_api 工程中的用戶服務 Web 層模塊,負責處理用戶相關的 HTTP 請求、參數校驗、業務路由以及調用後端接口等功能。以下是目錄結構說明: user-web/ ├── api/ # 控制器層,定義業務接口處理邏輯 ├── config/ # 配置模塊,包含系統配置結構體及讀取邏輯 …

簡體中文 繁體中文 English