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/6781

(0)
Walker的頭像Walker
上一篇 10小時前
下一篇 2025年3月8日 12:51

相關推薦

  • Go資深工程師講解(慕課) 005

    005 標準庫 http 使用 http 客戶端發送請求 使用 http.Client 控制請求頭 使用 httputil 簡化工作 package main import ( "fmt" "net/http" "net/http/httputil" ) func main() { resp, er…

    後端開發 21小時前
    100
  • 編程基礎 0007_併發模式

    Go 併發模式 常見的 Go 併發設計模式,每個模式都有完整可運行示例和適用場景說明 1. Worker Pool 模式 固定數量的 worker goroutine 從共享的任務隊列中取任務執行,控制併發度。 package main import ( "fmt" "sync" "time" ) …

    後端開發 15小時前
    000
  • Go日積月累 電子書目錄與推薦

    Go 語言電子書精華整理與推薦 基於 48 份 Go 語言電子書資料,按主題提煉為 4 篇系統化精華文檔。整理時間:2026-03-06 精華文章導讀 以下 4 篇文章從 48 份電子書中提煉核心知識,按主題系統化整理,覆蓋 Go 語言從底層原理到企業實戰的完整知識體系。 1. Go 底層原理與源碼精華 知識來源:《Go 源碼剖析》(雨痕)、《Go 1.4 …

  • Go工程師體系課 012

    Go 中集成 Elasticsearch 1. 客戶端庫選擇 1.1 主流 Go ES 客戶端 olivere/elastic:功能最全面,API 設計優雅,支持 ES 7.x/8.x elastic/go-elasticsearch:官方客戶端,輕量級,更接近原生 REST API go-elasticsearch/elasticsearch:社區維護的官…

    後端開發 1小時前
    000
  • Go工程師體系課 006

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

簡體中文 繁體中文 English