91欧美超碰AV自拍|国产成年人性爱视频免费看|亚洲 日韩 欧美一厂二区入|人人看人人爽人人操aV|丝袜美腿视频一区二区在线看|人人操人人爽人人爱|婷婷五月天超碰|97色色欧美亚州A√|另类A√无码精品一级av|欧美特级日韩特级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Docker容器化部署完全指南

馬哥Linux運(yùn)維 ? 來(lái)源:馬哥Linux運(yùn)維 ? 2026-02-09 14:09 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

Docker 容器化部署完全指南:從安裝到生產(chǎn)環(huán)境最佳實(shí)踐

一、概述

1.1 背景介紹

Docker 解決的核心問(wèn)題就一個(gè):"在我機(jī)器上能跑,到你那就不行了"。通過(guò)將應(yīng)用及其依賴打包成鏡像,保證開(kāi)發(fā)、測(cè)試、生產(chǎn)環(huán)境完全一致。容器秒級(jí)啟動(dòng)(實(shí)測(cè)冷啟動(dòng) 0.5-2 秒),鏡像分層復(fù)用節(jié)省存儲(chǔ)和傳輸成本——一個(gè) 200MB 的基礎(chǔ)鏡像被 50 個(gè)應(yīng)用共享,每個(gè)應(yīng)用只需額外存儲(chǔ)自己的差異層。

我們團(tuán)隊(duì)從 2019 年開(kāi)始全面容器化,目前線上跑著 800+ 個(gè)容器,覆蓋 Java、Go、Node.jsPython 四種技術(shù)棧。這篇文章把從安裝到生產(chǎn)環(huán)境踩過(guò)的坑全部整理出來(lái)。

1.2 技術(shù)特點(diǎn)

環(huán)境一致性:鏡像即環(huán)境,開(kāi)發(fā)用的鏡像和生產(chǎn)用的完全一樣,徹底消除環(huán)境差異導(dǎo)致的問(wèn)題

秒級(jí)啟動(dòng):容器不需要啟動(dòng)完整操作系統(tǒng),直接運(yùn)行應(yīng)用進(jìn)程,啟動(dòng)速度比虛擬機(jī)快 10-100 倍

分層存儲(chǔ):鏡像由多層只讀層組成,相同的層在多個(gè)鏡像間共享,節(jié)省磁盤(pán)空間和網(wǎng)絡(luò)傳輸

資源隔離:基于 Linux cgroup 和 namespace 實(shí)現(xiàn) CPU、內(nèi)存、網(wǎng)絡(luò)、文件系統(tǒng)隔離,互不干擾

聲明式編排:通過(guò) Dockerfile 和 docker-compose.yml 聲明式定義應(yīng)用環(huán)境,版本可控、可復(fù)現(xiàn)

1.3 適用場(chǎng)景

應(yīng)用容器化部署:將傳統(tǒng)應(yīng)用打包成容器,統(tǒng)一部署和管理方式,降低運(yùn)維復(fù)雜度

微服務(wù)架構(gòu):每個(gè)微服務(wù)獨(dú)立容器化,獨(dú)立部署、獨(dú)立擴(kuò)縮容,服務(wù)間通過(guò)網(wǎng)絡(luò)通信

CI/CD 流水線:構(gòu)建環(huán)境容器化,保證每次構(gòu)建環(huán)境一致;測(cè)試環(huán)境秒級(jí)創(chuàng)建和銷毀

開(kāi)發(fā)測(cè)試環(huán)境標(biāo)準(zhǔn)化:新人入職docker compose up一條命令拉起整套開(kāi)發(fā)環(huán)境,不用花半天裝依賴

1.4 環(huán)境要求

組件 版本要求 說(shuō)明
操作系統(tǒng) CentOS 7+ / Ubuntu 20.04+ 推薦 Ubuntu 22.04 LTS,內(nèi)核 5.15+ 對(duì) overlay2 和 cgroup v2 支持更好
Linux 內(nèi)核 4.x+(推薦 5.x+) 內(nèi)核 5.x 的 overlay2 性能更好,cgroup v2 支持更完善
Docker CE 24.0+(推薦 27.x) 24.0 開(kāi)始默認(rèn)使用 BuildKit,27.x 是當(dāng)前最新穩(wěn)定版
Docker Compose V2(docker compose) V1(docker-compose)已停止維護(hù),V2 作為 Docker CLI 插件集成
硬件配置 2C4G 起步 跑 10 個(gè)以內(nèi)容器 2C4G 夠用,20+ 容器建議 4C8G 起步
存儲(chǔ) SSD 推薦 overlay2 存儲(chǔ)驅(qū)動(dòng)在 SSD 上性能明顯優(yōu)于 HDD

二、詳細(xì)步驟

2.1 準(zhǔn)備工作

2.1.1 系統(tǒng)檢查

# 檢查系統(tǒng)版本
cat /etc/os-release

# 檢查內(nèi)核版本(建議 5.x+)
uname -r

# 檢查是否支持 overlay2(生產(chǎn)環(huán)境必須用 overlay2)
cat /proc/filesystems | grep overlay

# 檢查可用磁盤(pán)空間(Docker 鏡像和容器數(shù)據(jù)會(huì)占用大量空間)
df -h

# 檢查是否已安裝舊版本 Docker
docker --version 2>/dev/null &&echo"Docker 已安裝"||echo"Docker 未安裝"

2.1.2 卸載舊版本

舊版本的包名可能是docker、docker.io、docker-engine,必須先卸載干凈:

# Ubuntu/Debian
sudo apt remove -y docker docker-engine docker.io containerd runc 2>/dev/null
sudo apt autoremove -y

# CentOS/Rocky Linux
sudo yum remove -y docker docker-client docker-client-latest 
  docker-common docker-latest docker-latest-logrotate 
  docker-logrotate docker-engine 2>/dev/null

注意:卸載舊版本不會(huì)刪除/var/lib/docker/下的鏡像、容器和卷數(shù)據(jù)。如果要全新安裝,手動(dòng)刪除:

# 這個(gè)操作會(huì)刪除所有鏡像和容器數(shù)據(jù),執(zhí)行前確認(rèn)不需要保留
sudo rm -rf /var/lib/docker
sudo rm -rf /var/lib/containerd

2.2 安裝 Docker CE

2.2.1 Ubuntu/Debian 安裝

# 安裝必要工具
sudo apt update
sudo apt install -y ca-certificates curl gnupg lsb-release

# 添加 Docker 官方 GPG 密鑰
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

# 添加 Docker 官方源
echo
"deb [arch=$(dpkg --print-architecture)signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu 
$(. /etc/os-release && echo "$VERSION_CODENAME")stable"| 
 sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 安裝 Docker CE + CLI + containerd + Compose 插件 + BuildKit
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io 
  docker-buildx-plugin docker-compose-plugin

# 驗(yàn)證安裝
docker --version
docker compose version

2.2.2 CentOS/Rocky Linux 安裝

# 安裝 yum-utils(提供 yum-config-manager)
sudo yum install -y yum-utils

# 添加 Docker 官方源
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

# 啟動(dòng)并設(shè)置開(kāi)機(jī)自啟
sudo systemctl start docker
sudo systemctlenabledocker

# 驗(yàn)證
docker --version
docker compose version

2.2.3 配置非 root 用戶運(yùn)行 Docker

生產(chǎn)環(huán)境不建議用 root 跑 Docker 命令,把用戶加到 docker 組即可:

# 創(chuàng)建 docker 組(安裝時(shí)通常已自動(dòng)創(chuàng)建)
sudo groupadd docker 2>/dev/null

# 將當(dāng)前用戶加入 docker 組
sudo usermod -aG docker$USER

# 重新登錄使組權(quán)限生效(或執(zhí)行以下命令臨時(shí)生效)
newgrp docker

# 驗(yàn)證非 root 用戶可以運(yùn)行 docker
docker run hello-world

注意:docker 組的用戶等同于擁有 root 權(quán)限(可以掛載宿主機(jī)任意目錄),只把可信用戶加入該組。

2.3 daemon.json 生產(chǎn)環(huán)境配置

這是我們線上所有 Docker 主機(jī)統(tǒng)一使用的 daemon.json,每個(gè)參數(shù)都有明確的理由:

{
"storage-driver":"overlay2",
"log-driver":"json-file",
"log-opts": {
 "max-size":"100m",
 "max-file":"3"
 },
"registry-mirrors": [
 "https://mirror.ccs.tencentyun.com",
 "https://docker.mirrors.ustc.edu.cn"
 ],
"insecure-registries": [
 "harbor.internal.example.com:5000"
 ],
"live-restore":true,
"default-ulimits": {
 "nofile": {
  "Name":"nofile",
  "Hard":65535,
  "Soft":65535
  }
 },
"bip":"172.17.0.1/16",
"default-address-pools": [
  {
  "base":"172.18.0.0/16",
  "size":24
  }
 ],
"max-concurrent-downloads":10,
"max-concurrent-uploads":5,
"features": {
 "buildkit":true
 }
}

參數(shù)說(shuō)明

storage-driver: overlay2:生產(chǎn)環(huán)境唯一推薦的存儲(chǔ)驅(qū)動(dòng),性能和穩(wěn)定性最好。舊版本的 aufs/devicemapper 已廢棄

log-driver: json-file+max-size/max-file:限制每個(gè)容器日志最大 100MB,保留 3 個(gè)文件。這個(gè)必須配,否則日志會(huì)撐爆磁盤(pán)。線上出過(guò)好幾次磁盤(pán) 100% 的事故,都是沒(méi)限制日志大小導(dǎo)致的

registry-mirrors:鏡像加速器,國(guó)內(nèi)拉 Docker Hub 鏡像很慢,配了加速器后拉取速度從幾十 KB/s 提升到幾 MB/s

insecure-registries:內(nèi)網(wǎng) Harbor 私有倉(cāng)庫(kù)如果沒(méi)配 HTTPS,必須加到這里,否則 push/pull 會(huì)報(bào)證書(shū)錯(cuò)誤

live-restore: true:Docker daemon 重啟時(shí)不殺容器。升級(jí) Docker 版本或重啟 dockerd 時(shí),正在運(yùn)行的容器不受影響。生產(chǎn)環(huán)境必開(kāi)

bip:自定義 docker0 網(wǎng)橋的網(wǎng)段。默認(rèn) 172.17.0.0/16 可能和公司內(nèi)網(wǎng)沖突,提前規(guī)劃好

default-address-pools:自定義容器網(wǎng)絡(luò)的地址池,避免docker network create時(shí)分配到已被占用的網(wǎng)段

max-concurrent-downloads: 10:并行拉取鏡像層數(shù),默認(rèn) 3 太少,設(shè)為 10 加快拉取速度

# 寫(xiě)入配置后重啟 Docker
sudo mkdir -p /etc/docker
sudo vim /etc/docker/daemon.json # 寫(xiě)入上面的配置
sudo systemctl daemon-reload
sudo systemctl restart docker

# 驗(yàn)證配置生效
docker info | grep -E"Storage Driver|Logging Driver|Registry Mirrors|Live Restore"

2.4 Dockerfile 最佳實(shí)踐

2.4.1 多階段構(gòu)建

多階段構(gòu)建是減小鏡像體積最有效的手段。編譯階段用完整的 SDK 鏡像,運(yùn)行階段只用最小的 runtime 鏡像。

Go 應(yīng)用示例(從 1.2GB 壓縮到 15MB):

# 文件名:Dockerfile
# 階段一:編譯
FROMgolang:1.22-alpine AS builder

WORKDIR/app

# 先復(fù)制 go.mod/go.sum,利用緩存(依賴不變時(shí)不重新下載)
COPYgo.mod go.sum ./
RUNgo mod download

# 再?gòu)?fù)制源碼
COPY. .

# 編譯為靜態(tài)二進(jìn)制(CGO_ENABLED=0 不依賴 C 庫(kù))
RUNCGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w"-o /app/server ./cmd/server

# 階段二:運(yùn)行
FROMalpine:3.19

# 安裝必要的 CA 證書(shū)(HTTPS 請(qǐng)求需要)和時(shí)區(qū)數(shù)據(jù)
RUNapk --no-cache add ca-certificates tzdata

# 非 root 用戶運(yùn)行
RUNaddgroup -S appgroup && adduser -S appuser -G appgroup

WORKDIR/app
COPY--from=builder /app/server .
COPY--from=builder /app/configs ./configs

# 設(shè)置時(shí)區(qū)
ENVTZ=Asia/Shanghai

USERappuser

EXPOSE8080

HEALTHCHECK--interval=30s --timeout=3s --start-period=5s --retries=3 
  CMD wget -qO- http://localhost:8080/health ||exit1

ENTRYPOINT["./server"]

實(shí)測(cè)結(jié)果:

不用多階段構(gòu)建:golang:1.22 基礎(chǔ)鏡像 1.2GB + 應(yīng)用 = 約 1.3GB

多階段構(gòu)建用 alpine:15MB

Java Spring Boot 應(yīng)用示例:

# 文件名:Dockerfile
# 階段一:構(gòu)建
FROMmaven:3.9-eclipse-temurin-21AS builder

WORKDIR/app
COPYpom.xml .
# 先下載依賴(利用緩存層)
RUNmvn dependency:go-offline -B

COPYsrc ./src
RUNmvn package -DskipTests -B

# 解壓 Spring Boot fat jar(分層優(yōu)化)
RUNjava -Djarmode=layertools -jar target/*.jar extract --destination /extracted

# 階段二:運(yùn)行
FROMeclipse-temurin:21-jre-alpine

RUNaddgroup -S appgroup && adduser -S appuser -G appgroup

WORKDIR/app

# 按變化頻率從低到高復(fù)制(充分利用緩存)
COPY--from=builder /extracted/dependencies/ ./
COPY--from=builder /extracted/spring-boot-loader/ ./
COPY--from=builder /extracted/snapshot-dependencies/ ./
COPY--from=builder /extracted/application/ ./

ENVTZ=Asia/Shanghai
ENVJAVA_OPTS="-Xms512m -Xmx512m -XX:+UseG1GC"

USERappuser

EXPOSE8080

HEALTHCHECK--interval=30s --timeout=5s --start-period=30s --retries=3 
  CMD wget -qO- http://localhost:8080/actuator/health ||exit1

ENTRYPOINT["sh","-c","java$JAVA_OPTSorg.springframework.boot.loader.launch.JarLauncher"]

實(shí)測(cè)結(jié)果:

不用多階段構(gòu)建:maven 基礎(chǔ)鏡像 800MB + 應(yīng)用 = 約 900MB

多階段構(gòu)建用 JRE alpine:約 180MB

2.4.2 .dockerignore 文件

構(gòu)建上下文會(huì)把當(dāng)前目錄所有文件發(fā)送給 Docker daemon,不配 .dockerignore 會(huì)把 node_modules、.git 等無(wú)關(guān)文件也發(fā)過(guò)去,構(gòu)建慢且鏡像臃腫。

# 文件名:.dockerignore
.git
.gitignore
.dockerignore
Dockerfile
docker-compose*.yml
README.md
LICENSE
docs/

# Node.js
node_modules
npm-debug.log

# Go
vendor/

# Java
target/
*.jar
*.class

# Python
__pycache__
*.pyc
.venv
venv

# IDE
.idea
.vscode
*.swp
*.swo

# 環(huán)境變量文件(絕對(duì)不能打進(jìn)鏡像)
.env
.env.*

這個(gè)文件必須有,特別是.env文件絕對(duì)不能打進(jìn)鏡像,里面有數(shù)據(jù)庫(kù)密碼等敏感信息。

2.4.3 Dockerfile 編寫(xiě)要點(diǎn)

COPY vs ADD:優(yōu)先用 COPY,語(yǔ)義明確。ADD 會(huì)自動(dòng)解壓 tar 包和支持 URL 下載,容易產(chǎn)生意外行為

RUN 合并減少層數(shù):每條 RUN 指令生成一層,合并可以減小鏡像體積

# 錯(cuò)誤寫(xiě)法:3 層,且第一層的 apt cache 無(wú)法被清理掉
RUNapt update
RUNapt install -y curl wget
RUNrm -rf /var/lib/apt/lists/*

# 正確寫(xiě)法:1 層,安裝完立即清理緩存
RUNapt update && apt install -y --no-install-recommends curl wget 
  && rm -rf /var/lib/apt/lists/*

非 root USER:容器默認(rèn)以 root 運(yùn)行,安全風(fēng)險(xiǎn)大。生產(chǎn)環(huán)境必須創(chuàng)建專用用戶

HEALTHCHECK:定義健康檢查,Docker 和編排工具(Compose/Swarm/K8s)據(jù)此判斷容器是否正常

ARG vs ENV:ARG 只在構(gòu)建階段可用(如版本號(hào)),ENV 在運(yùn)行時(shí)也可用(如配置參數(shù))

2.5 Docker Compose 編排

2.5.1 完整的多服務(wù)編排示例

以下是一個(gè)典型的 Web 應(yīng)用編排:Nginx 反向代理 + Node.js API + MySQL + Redis,包含健康檢查、啟動(dòng)順序控制、資源限制。

# 文件名:docker-compose.yml

services:
# Nginx 反向代理
nginx:
 image:nginx:1.24-alpine
 container_name:app-nginx
 ports:
  -"80:80"
  -"443:443"
 volumes:
  -./nginx/conf.d:/etc/nginx/conf.d:ro
  -./nginx/ssl:/etc/nginx/ssl:ro
  -./frontend/dist:/var/www/html:ro
  -nginx-logs:/var/log/nginx
 depends_on:
  api:
   condition:service_healthy
 restart:unless-stopped
 deploy:
  resources:
   limits:
    cpus:'1.0'
    memory:256M
 networks:
  -frontend

# Node.js API 服務(wù)
api:
 build:
  context:./api
  dockerfile:Dockerfile
 container_name:app-api
 env_file:
  -.env
 environment:
  -NODE_ENV=production
  -DB_HOST=mysql
  -DB_PORT=3306
  -REDIS_HOST=redis
  -REDIS_PORT=6379
 depends_on:
  mysql:
   condition:service_healthy
  redis:
   condition:service_healthy
 healthcheck:
  test:["CMD","wget","-qO-","http://localhost:3000/health"]
  interval:15s
  timeout:5s
  retries:3
  start_period:10s
 restart:unless-stopped
 deploy:
  resources:
   limits:
    cpus:'2.0'
    memory:1G
   reservations:
    cpus:'0.5'
    memory:256M
 networks:
  -frontend
  -backend

# MySQL 數(shù)據(jù)庫(kù)
mysql:
 image:mysql:8.0
 container_name:app-mysql
 environment:
  MYSQL_ROOT_PASSWORD:${MYSQL_ROOT_PASSWORD}
  MYSQL_DATABASE:${MYSQL_DATABASE}
  MYSQL_USER:${MYSQL_USER}
  MYSQL_PASSWORD:${MYSQL_PASSWORD}
 volumes:
  -mysql-data:/var/lib/mysql
  -./mysql/conf.d:/etc/mysql/conf.d:ro
  -./mysql/init:/docker-entrypoint-initdb.d:ro
 healthcheck:
  test:["CMD","mysqladmin","ping","-h","localhost","-u","root","-p${MYSQL_ROOT_PASSWORD}"]
  interval:10s
  timeout:5s
  retries:5
  start_period:30s
 restart:unless-stopped
 deploy:
  resources:
   limits:
    cpus:'2.0'
    memory:2G
 command:>
   --character-set-server=utf8mb4
   --collation-server=utf8mb4_unicode_ci
   --max-connections=500
   --innodb-buffer-pool-size=1G
 networks:
  -backend

# Redis 緩存
redis:
 image:redis:7-alpine
 container_name:app-redis
 command:>
   redis-server
   --requirepass ${REDIS_PASSWORD}
   --maxmemory 512mb
   --maxmemory-policy allkeys-lru
   --appendonly yes
 volumes:
  -redis-data:/data
 healthcheck:
  test:["CMD","redis-cli","-a","${REDIS_PASSWORD}","ping"]
  interval:10s
  timeout:3s
  retries:3
 restart:unless-stopped
 deploy:
  resources:
   limits:
    cpus:'1.0'
    memory:768M
 networks:
  -backend

networks:
frontend:
 driver:bridge
backend:
 driver:bridge
 internal:true # 后端網(wǎng)絡(luò)不暴露到外部

volumes:
mysql-data:
redis-data:
nginx-logs:

配套 .env 文件:

# 文件名:.env(不要提交到 Git)
MYSQL_ROOT_PASSWORD=your_root_password_here
MYSQL_DATABASE=app_production
MYSQL_USER=app_user
MYSQL_PASSWORD=your_app_password_here
REDIS_PASSWORD=your_redis_password_here

常用操作命令:

# 啟動(dòng)所有服務(wù)(后臺(tái)運(yùn)行)
docker compose up -d

# 查看服務(wù)狀態(tài)
docker compose ps

# 查看某個(gè)服務(wù)的日志
docker compose logs -f api

# 重新構(gòu)建并啟動(dòng)
docker compose up -d --build

# 停止所有服務(wù)(保留數(shù)據(jù)卷)
docker compose down

# 停止并刪除數(shù)據(jù)卷(慎用,會(huì)丟數(shù)據(jù))
docker compose down -v

2.6 網(wǎng)絡(luò)模式

2.6.1 網(wǎng)絡(luò)模式對(duì)比

模式 說(shuō)明 適用場(chǎng)景
bridge 默認(rèn)模式,容器通過(guò)虛擬網(wǎng)橋通信 大部分場(chǎng)景
host 容器直接使用宿主機(jī)網(wǎng)絡(luò)棧 對(duì)網(wǎng)絡(luò)性能要求極高的場(chǎng)景(如監(jiān)控采集)
none 無(wú)網(wǎng)絡(luò),完全隔離 安全敏感的離線計(jì)算任務(wù)
overlay 跨主機(jī)容器通信(Swarm 模式) Docker Swarm 集群
macvlan 容器擁有獨(dú)立 MAC 地址,直接接入物理網(wǎng)絡(luò) 需要容器有獨(dú)立 IP 的傳統(tǒng)網(wǎng)絡(luò)環(huán)境

2.6.2 自定義網(wǎng)絡(luò)

生產(chǎn)環(huán)境不要用默認(rèn)的 bridge 網(wǎng)絡(luò),自定義網(wǎng)絡(luò)有 DNS 解析功能(容器間可以用容器名互相訪問(wèn)):

# 創(chuàng)建自定義網(wǎng)絡(luò)(指定網(wǎng)段,避免和內(nèi)網(wǎng)沖突)
docker network create 
  --driver bridge 
  --subnet 172.20.0.0/24 
  --gateway 172.20.0.1 
  app-network

# 查看網(wǎng)絡(luò)詳情
docker network inspect app-network

# 將已運(yùn)行的容器接入網(wǎng)絡(luò)
docker network connect app-network my-container

# 斷開(kāi)網(wǎng)絡(luò)
docker network disconnect app-network my-container

注意:默認(rèn) bridge 網(wǎng)絡(luò)(docker0)不支持容器名 DNS 解析,只有自定義網(wǎng)絡(luò)才支持。這是很多人踩的坑——在默認(rèn)網(wǎng)絡(luò)里用容器名訪問(wèn)另一個(gè)容器,永遠(yuǎn)連不上。

2.7 存儲(chǔ)卷

2.7.1 三種掛載方式對(duì)比

類型 命令示例 數(shù)據(jù)位置 適用場(chǎng)景
Named Volume -v mydata:/data Docker 管理(/var/lib/docker/volumes/) 數(shù)據(jù)庫(kù)、持久化數(shù)據(jù)
Bind Mount -v /host/path:/container/path 宿主機(jī)指定目錄 配置文件、代碼熱更新
tmpfs --tmpfs /tmp 內(nèi)存 臨時(shí)文件、敏感數(shù)據(jù)(不落盤(pán))

2.7.2 Named Volume 數(shù)據(jù)持久化

# 創(chuàng)建命名卷
docker volume create mysql-data

# 查看卷詳情
docker volume inspect mysql-data

# 使用命名卷啟動(dòng) MySQL
docker run -d 
  --name mysql 
  -v mysql-data:/var/lib/mysql 
  -e MYSQL_ROOT_PASSWORD=secret 
  mysql:8.0

# 備份卷數(shù)據(jù)
docker run --rm 
  -v mysql-data:/source:ro 
  -v $(pwd):/backup 
  alpine tar czf /backup/mysql-data-backup.tar.gz -C /source.

# 恢復(fù)卷數(shù)據(jù)
docker run --rm 
  -v mysql-data:/target 
  -v $(pwd):/backup 
  alpine tar xzf /backup/mysql-data-backup.tar.gz -C /target

注意:docker compose down -v會(huì)刪除所有命名卷,數(shù)據(jù)庫(kù)數(shù)據(jù)會(huì)丟失。生產(chǎn)環(huán)境執(zhí)行前務(wù)必確認(rèn),或者養(yǎng)成習(xí)慣只用docker compose down(不加 -v)。

三、示例代碼和配置

3.1 完整配置示例

3.1.1 daemon.json 生產(chǎn)環(huán)境完整配置(帶注釋版)

// 文件路徑:/etc/docker/daemon.json
// 注意:實(shí)際 JSON 文件不支持注釋,這里僅作說(shuō)明
{
 // 存儲(chǔ)驅(qū)動(dòng),生產(chǎn)環(huán)境只用 overlay2
 "storage-driver": "overlay2",

 // 日志驅(qū)動(dòng)和限制(防止日志撐爆磁盤(pán))
 "log-driver": "json-file",
 "log-opts": {
  "max-size": "100m",
  "max-file": "3"
 },

 // 鏡像加速器(按需配置)
 "registry-mirrors": [
  "https://mirror.ccs.tencentyun.com"
 ],

 // 內(nèi)網(wǎng)私有倉(cāng)庫(kù)(HTTP 協(xié)議)
 "insecure-registries": [
  "harbor.internal.example.com:5000"
 ],

 // Docker daemon 重啟時(shí)保持容器運(yùn)行
 "live-restore": true,

 // 容器默認(rèn) ulimit
 "default-ulimits": {
  "nofile": { "Name": "nofile", "Hard": 65535, "Soft": 65535 },
  "nproc": { "Name": "nproc", "Hard": 65535, "Soft": 65535 }
 },

 // 自定義 docker0 網(wǎng)橋網(wǎng)段
 "bip": "172.17.0.1/16",

 // 自定義容器網(wǎng)絡(luò)地址池
 "default-address-pools": [
  { "base": "172.18.0.0/16", "size": 24 }
 ],

 // 并行下載/上傳層數(shù)
 "max-concurrent-downloads": 10,
 "max-concurrent-uploads": 5,

 // 啟用 BuildKit(構(gòu)建速度更快,支持緩存掛載)
 "features": { "buildkit": true },

 // 數(shù)據(jù)根目錄(默認(rèn) /var/lib/docker,磁盤(pán)不夠時(shí)可改到大盤(pán))
 "data-root": "/var/lib/docker",

 // DNS 配置(容器內(nèi) DNS 解析)
 "dns": ["8.8.8.8", "114.114.114.114"]
}

3.1.2 Makefile 封裝常用 Docker 操作

團(tuán)隊(duì)協(xié)作時(shí),用 Makefile 封裝常用命令,新人不用記一堆 docker 參數(shù):

# 文件名:Makefile

APP_NAME := myapp
VERSION :=$(shellgit describe --tags --always --dirty 2>/dev/null || echo "dev")
REGISTRY := harbor.internal.example.com:5000
IMAGE  :=$(REGISTRY)/$(APP_NAME):$(VERSION)

.PHONY: build push run stop logs clean

# 構(gòu)建鏡像
build:
docker build -t$(IMAGE)-t$(REGISTRY)/$(APP_NAME):latest .

# 推送到私有倉(cāng)庫(kù)
push: build
docker push$(IMAGE)
docker push$(REGISTRY)/$(APP_NAME):latest

# 本地運(yùn)行
run:
docker compose up -d

# 停止服務(wù)
stop:
docker compose down

# 查看日志
logs:
docker compose logs -f --tail=100

# 清理懸空鏡像和停止的容器
clean:
docker system prune -f
docker image prune -f

# 進(jìn)入容器 shell
shell:
docker compose exec api sh

# 數(shù)據(jù)庫(kù)備份
db-backup:
docker compose exec mysql mysqldump -u root -p$(MYSQL_ROOT_PASSWORD)$(MYSQL_DATABASE)> backup_$(shelldate +%Y%m%d_%H%M%S).sql

# 查看資源使用
stats:
docker stats --no-stream

3.2 實(shí)際應(yīng)用案例

案例一:Node.js 應(yīng)用容器化部署

場(chǎng)景描述:將一個(gè) Express.js API 服務(wù)容器化,配合 PM2 進(jìn)程管理,實(shí)現(xiàn)生產(chǎn)級(jí)部署。

Dockerfile:

FROMnode:20-alpine AS builder

WORKDIR/app
COPYpackage*.json ./
RUNnpm ci --only=production && npm cache clean --force

FROMnode:20-alpine

RUNapk --no-cache add tini
RUNaddgroup -S appgroup && adduser -S appuser -G appgroup

WORKDIR/app
COPY--from=builder /app/node_modules ./node_modules
COPY. .

ENVNODE_ENV=production
USERappuser
EXPOSE3000

HEALTHCHECK--interval=30s --timeout=3s --retries=3 
  CMD wget -qO- http://localhost:3000/health ||exit1

# 用 tini 作為 PID 1(正確處理信號(hào),避免僵尸進(jìn)程)
ENTRYPOINT["/sbin/tini","--"]
CMD["node","src/index.js"]

運(yùn)行結(jié)果

$ docker build -t myapi:1.0 .
$ docker images myapi
REPOSITORY  TAG  IMAGE ID    SIZE
myapi    1.0  a1b2c3d4e5f6  95MB

# 對(duì)比不用多階段構(gòu)建:約 350MB

案例二:零停機(jī)滾動(dòng)更新

場(chǎng)景描述:生產(chǎn)環(huán)境更新應(yīng)用版本,不中斷服務(wù)。通過(guò) docker compose 配合 Nginx upstream 實(shí)現(xiàn)。

實(shí)現(xiàn)步驟

構(gòu)建新版本鏡像并推送到倉(cāng)庫(kù)

拉取新鏡像,啟動(dòng)新容器

健康檢查通過(guò)后,切換 Nginx 流量到新容器

停止舊容器

#!/bin/bash
# 文件名:rolling-update.sh
# 零停機(jī)滾動(dòng)更新腳本

set-e

APP_NAME="app-api"
NEW_IMAGE="$1"

if[ -z"$NEW_IMAGE"];then
 echo"用法:$0"
 exit1
fi

echo"[1/5] 拉取新鏡像:$NEW_IMAGE"
docker pull"$NEW_IMAGE"

echo"[2/5] 啟動(dòng)新容器"
docker compose up -d --no-deps --scale api=2 api

echo"[3/5] 等待新容器健康檢查通過(guò)..."
sleep 10
NEW_CONTAINER=$(docker compose ps -q api | tail -1)
foriin$(seq 1 30);do
  STATUS=$(docker inspect --format='{{.State.Health.Status}}'"$NEW_CONTAINER"2>/dev/null)
 if["$STATUS"="healthy"];then
   echo"新容器健康檢查通過(guò)"
   break
 fi
 echo"等待中... ($i/30)"
  sleep 2
done

echo"[4/5] 縮容,移除舊容器"
docker compose up -d --no-deps --scale api=1 api

echo"[5/5] 清理舊鏡像"
docker image prune -f

echo"更新完成!"

四、最佳實(shí)踐和注意事項(xiàng)

4.1 最佳實(shí)踐

4.1.1 鏡像瘦身

選擇合適的基礎(chǔ)鏡像

基礎(chǔ)鏡像 大小 適用場(chǎng)景
ubuntu:22.04 77MB 需要完整包管理器的場(chǎng)景
debian:bookworm-slim 74MB 需要 glibc 但不需要完整 Debian
alpine:3.19 7MB Go/Rust 等靜態(tài)編譯語(yǔ)言,體積最小
distroless 2-20MB 安全要求最高的場(chǎng)景,無(wú) shell 無(wú)包管理器
scratch 0MB 純靜態(tài)二進(jìn)制,如 Go 應(yīng)用

我們團(tuán)隊(duì)的做法:Go 應(yīng)用用 alpine,Java 應(yīng)用用 eclipse-temurin JRE alpine,Node.js 用 node alpine。

用 dive 分析鏡像層

# 安裝 dive
wget https://github.com/wagoodman/dive/releases/download/v0.12.0/dive_0.12.0_linux_amd64.tar.gz
tar -zxvf dive_0.12.0_linux_amd64.tar.gz
sudo mv dive /usr/local/bin/

# 分析鏡像每一層的內(nèi)容和大小
dive myapp:latest

dive 會(huì)顯示每一層新增了哪些文件、占了多少空間,能快速定位鏡像臃腫的原因。實(shí)測(cè)用 dive 分析后,我們把一個(gè) Java 鏡像從 600MB 優(yōu)化到 180MB。

4.1.2 安全加固

非 root 運(yùn)行:容器默認(rèn)以 root 運(yùn)行,一旦容器逃逸攻擊者就是宿主機(jī) root。Dockerfile 中必須創(chuàng)建專用用戶:

RUNaddgroup -S appgroup && adduser -S appuser -G appgroup
USERappuser

只讀文件系統(tǒng):容器運(yùn)行時(shí)文件系統(tǒng)設(shè)為只讀,防止惡意寫(xiě)入:

docker run --read-only --tmpfs /tmp --tmpfs /var/run myapp:latest

需要寫(xiě)入的目錄用 tmpfs 或 volume 掛載。

Drop 不需要的 Linux Capabilities

# 移除所有 capabilities,只保留需要的
docker run --cap-drop ALL --cap-add NET_BIND_SERVICE myapp:latest

默認(rèn)容器有 14 個(gè) capabilities,大部分應(yīng)用只需要 1-2 個(gè)。全部 drop 再按需 add 是最安全的做法。

鏡像安全掃描

# 用 Trivy 掃描鏡像漏洞(推薦,速度快、數(shù)據(jù)庫(kù)全)
trivy image myapp:latest

# 只顯示高危和嚴(yán)重漏洞
trivy image --severity HIGH,CRITICAL myapp:latest

# 集成到 CI/CD:發(fā)現(xiàn)高危漏洞時(shí)構(gòu)建失敗
trivy image --exit-code 1 --severity HIGH,CRITICAL myapp:latest

我們團(tuán)隊(duì)在 CI 流水線中強(qiáng)制掃描,HIGH 以上漏洞必須修復(fù)才能上線。

4.1.3 日志管理

json-file 驅(qū)動(dòng)限制大小(daemon.json 中已配置):

{
"log-driver":"json-file",
"log-opts": {
 "max-size":"100m",
 "max-file":"3"
 }
}

每個(gè)容器最多 3 個(gè)日志文件,每個(gè) 100MB,總共 300MB 上限。不配這個(gè),跑幾天日志就能把磁盤(pán)撐爆。

單個(gè)容器覆蓋全局日志配置

# docker-compose.yml 中
services:
api:
 logging:
  driver:json-file
  options:
   max-size:"200m"
   max-file:"5"

集中日志收集方案

# 用 fluentd 驅(qū)動(dòng)將日志發(fā)送到集中式日志平臺(tái)
services:
api:
 logging:
  driver:fluentd
  options:
   fluentd-address:"10.0.0.50:24224"
   tag:"docker.{{.Name}}"
   fluentd-async:"true"

4.1.4 資源限制

容器不限制資源的話,一個(gè)容器內(nèi)存泄漏就能把整臺(tái)宿主機(jī)拖垮。生產(chǎn)環(huán)境必須設(shè)資源限制。

# 命令行方式限制資源
docker run -d 
  --name myapp 
  --memory 1g 
  --memory-swap 1g 
  --cpus 2.0 
  --pids-limit 200 
  --oom-score-adj 500 
  myapp:latest

參數(shù)說(shuō)明

--memory 1g:內(nèi)存上限 1GB,超過(guò)會(huì)觸發(fā) OOM Killer

--memory-swap 1g:設(shè)為和 memory 相同值表示禁用 swap(生產(chǎn)環(huán)境建議禁用,swap 會(huì)導(dǎo)致性能急劇下降)

--cpus 2.0:最多使用 2 個(gè) CPU 核心

--pids-limit 200:限制容器內(nèi)最大進(jìn)程數(shù),防止 fork 炸彈

--oom-score-adj 500:OOM 優(yōu)先級(jí),值越大越容易被 kill(保護(hù)宿主機(jī)上更重要的進(jìn)程)

4.1.5 CI/CD 集成

BuildKit 緩存加速構(gòu)建

# 啟用 BuildKit(daemon.json 中已配置,也可以通過(guò)環(huán)境變量臨時(shí)啟用)
exportDOCKER_BUILDKIT=1

# 使用緩存掛載加速依賴下載(Go 示例)
# Dockerfile 中:
# RUN --mount=type=cache,target=/go/pkg/mod go mod download
# RUN --mount=type=cache,target=/root/.cache/go-build go build -o /app/server

# 使用內(nèi)聯(lián)緩存(CI/CD 跨構(gòu)建復(fù)用緩存)
docker build 
  --build-arg BUILDKIT_INLINE_CACHE=1 
  --cache-from harbor.example.com/myapp:latest 
  -t harbor.example.com/myapp:v1.2.3 
  .

多平臺(tái)構(gòu)建(buildx)

# 創(chuàng)建多平臺(tái)構(gòu)建器
docker buildx create --name multiarch --use

# 同時(shí)構(gòu)建 amd64 和 arm64 鏡像并推送
docker buildx build 
  --platform linux/amd64,linux/arm64 
  -t harbor.example.com/myapp:v1.2.3 
  --push 
  .

ARM 服務(wù)器(如 AWS Graviton)越來(lái)越多,提前做好多平臺(tái)支持能省不少麻煩。

Harbor 私有倉(cāng)庫(kù)

# 登錄私有倉(cāng)庫(kù)
docker login harbor.internal.example.com:5000

# 打標(biāo)簽并推送
docker tag myapp:v1.2.3 harbor.internal.example.com:5000/project/myapp:v1.2.3
docker push harbor.internal.example.com:5000/project/myapp:v1.2.3

4.2 注意事項(xiàng)

4.2.1 配置注意事項(xiàng)

daemon.json 改錯(cuò)了會(huì)導(dǎo)致 Docker 無(wú)法啟動(dòng),改之前先備份。

修改 daemon.json 后必須systemctl daemon-reload && systemctl restart docker

live-restore: true時(shí)重啟 dockerd 不會(huì)殺容器,但升級(jí)大版本(如 24.x 到 27.x)時(shí)可能不兼容,建議先在測(cè)試環(huán)境驗(yàn)證

bip網(wǎng)段規(guī)劃要提前和網(wǎng)絡(luò)團(tuán)隊(duì)確認(rèn),避免和公司內(nèi)網(wǎng)、VPN 網(wǎng)段沖突。我們踩過(guò)的坑:默認(rèn) 172.17.0.0/16 和辦公網(wǎng) VPN 沖突,導(dǎo)致開(kāi)發(fā)機(jī)連不上容器

4.2.2 常見(jiàn)錯(cuò)誤

錯(cuò)誤現(xiàn)象 原因分析 解決方案
Cannot connect to the Docker daemon dockerd 未啟動(dòng)或權(quán)限不足 systemctl start docker 或?qū)⒂脩艏尤?docker 組
no space left on device 磁盤(pán)被鏡像/容器/日志占滿 docker system prune -a 清理;配置日志大小限制
OCI runtime create failed 內(nèi)核版本太低或 seccomp 配置問(wèn)題 升級(jí)內(nèi)核到 5.x+;檢查 seccomp profile
port is already allocated 端口被其他進(jìn)程占用 ss -tlnp | grep 找到占用進(jìn)程并處理
network has active endpoints 刪除網(wǎng)絡(luò)時(shí)還有容器在用 先停止并刪除使用該網(wǎng)絡(luò)的容器
image pull timeout DNS 解析失敗或網(wǎng)絡(luò)不通 檢查 DNS 配置;配置鏡像加速器

4.2.3 兼容性問(wèn)題

cgroup v1 vs v2:Ubuntu 22.04 默認(rèn)用 cgroup v2,部分老版本應(yīng)用(如 Java 8u191 以下)不識(shí)別 cgroup v2 的內(nèi)存限制,會(huì)導(dǎo)致 JVM 看到的是宿主機(jī)全部?jī)?nèi)存而非容器限制。解決辦法:升級(jí) JDK 版本或在 GRUB 中加systemd.unified_cgroup_hierarchy=0回退到 v1

Alpine 與 glibc:Alpine 用 musl libc 而非 glibc,部分依賴 glibc 的應(yīng)用(如某些 Python C 擴(kuò)展、Oracle JDK)在 Alpine 上會(huì)報(bào)錯(cuò)。解決辦法:換用 debian-slim 基礎(chǔ)鏡像,或安裝 gcompat 兼容層

Docker Compose V1 vs V2:V1(docker-compose,Python 實(shí)現(xiàn))已停止維護(hù),V2(docker compose,Go 實(shí)現(xiàn))是 Docker CLI 插件。兩者配置文件基本兼容,但部分邊緣行為有差異。新項(xiàng)目直接用 V2

五、故障排查和監(jiān)控

5.1 故障排查

5.1.1 日志查看

# 查看容器日志(最近 100 行,實(shí)時(shí)跟蹤)
docker logs --tail 100 -f 

# 查看指定時(shí)間段的日志
docker logs --since"2026-02-07T0000"--until"2026-02-07T1200"

# 查看 Docker daemon 日志
sudo journalctl -u docker -f

# 查看容器內(nèi)進(jìn)程
docker top 

# 查看容器詳細(xì)信息(啟動(dòng)參數(shù)、網(wǎng)絡(luò)、掛載等)
docker inspect 

# 查看容器事件流(啟動(dòng)、停止、OOM 等事件)
docker events --since"1h"

5.1.2 常見(jiàn)問(wèn)題排查

問(wèn)題一:容器啟動(dòng)后立即退出

# 查看退出碼
docker inspect --format='{{.State.ExitCode}}'

# 常見(jiàn)退出碼含義:
# 0  - 正常退出(CMD/ENTRYPOINT 執(zhí)行完畢)
# 1  - 應(yīng)用錯(cuò)誤
# 137 - 被 SIGKILL 殺死(通常是 OOM)
# 139 - 段錯(cuò)誤(Segmentation Fault)
# 143 - 被 SIGTERM 正常終止

# 查看最后的日志
docker logs --tail 50 

解決方案

退出碼 0:CMD 命令執(zhí)行完就退出了,需要一個(gè)前臺(tái)進(jìn)程保持運(yùn)行。常見(jiàn)錯(cuò)誤是用了CMD service nginx start(后臺(tái)啟動(dòng)后進(jìn)程退出),應(yīng)該用CMD ["nginx", "-g", "daemon off;"]

退出碼 137:容器被 OOM Killer 殺了,增大內(nèi)存限制或優(yōu)化應(yīng)用內(nèi)存使用

退出碼 1:應(yīng)用報(bào)錯(cuò),看日志找具體原因

問(wèn)題二:容器網(wǎng)絡(luò)不通

# 檢查容器網(wǎng)絡(luò)配置
docker inspect --format='{{json .NetworkSettings.Networks}}' | jq

# 進(jìn)入容器排查
dockerexec-it  sh

# 容器內(nèi)檢查 DNS
cat /etc/resolv.conf
nslookup mysql

# 容器內(nèi)檢查連通性
ping 
wget -qO- http://:/health

# 宿主機(jī)檢查 iptables 規(guī)則(Docker 通過(guò) iptables 實(shí)現(xiàn)端口映射和網(wǎng)絡(luò)隔離)
sudo iptables -t nat -L -n | grep 
sudo iptables -L DOCKER -n

解決方案

容器間互通但用容器名訪問(wèn)不了:檢查是否在同一個(gè)自定義網(wǎng)絡(luò)中,默認(rèn) bridge 網(wǎng)絡(luò)不支持 DNS

容器訪問(wèn)外網(wǎng)不通:檢查宿主機(jī)的 IP 轉(zhuǎn)發(fā)sysctl net.ipv4.ip_forward,值必須為 1

端口映射不生效:檢查宿主機(jī)防火墻規(guī)則,Docker 的 iptables 規(guī)則可能被其他防火墻工具覆蓋

問(wèn)題三:存儲(chǔ)空間耗盡

# 查看 Docker 磁盤(pán)使用情況
docker system df

# 詳細(xì)查看每個(gè)鏡像/容器/卷的占用
docker system df -v

# 查看 overlay2 存儲(chǔ)占用
du -sh /var/lib/docker/overlay2/* | sort -rh | head -20

解決方案

# 清理已停止的容器、未使用的網(wǎng)絡(luò)、懸空鏡像和構(gòu)建緩存
docker system prune -f

# 更激進(jìn)的清理:同時(shí)刪除未被任何容器使用的鏡像
docker system prune -a -f

# 只清理超過(guò) 24 小時(shí)的資源
docker system prune -a -f --filter"until=24h"

# 清理未使用的卷(數(shù)據(jù)庫(kù)卷要小心)
docker volume prune -f

預(yù)防措施:定期清理 + 日志大小限制 + 監(jiān)控磁盤(pán)使用率告警

問(wèn)題四:容器內(nèi)存 OOM

# 查看容器資源使用情況
docker stats --no-stream 

# 查看容器內(nèi)存限制
docker inspect --format='{{.HostConfig.Memory}}'

# 查看是否發(fā)生過(guò) OOM
docker inspect --format='{{.State.OOMKilled}}'

# 查看系統(tǒng) OOM 日志
dmesg | grep -i"oom|killed"

解決方案

確認(rèn)內(nèi)存限制是否合理:docker stats觀察實(shí)際內(nèi)存使用峰值,限制值設(shè)為峰值的 1.5 倍

Java 應(yīng)用特別注意:JVM 堆內(nèi)存(-Xmx)+ 非堆內(nèi)存(Metaspace、線程棧、NIO Buffer)總和不能超過(guò)容器內(nèi)存限制。經(jīng)驗(yàn)公式:容器內(nèi)存 = Xmx * 1.5

禁用 swap:--memory-swap設(shè)為和--memory相同值

5.2 性能監(jiān)控

5.2.1 docker stats 實(shí)時(shí)監(jiān)控

# 查看所有容器資源使用(實(shí)時(shí)刷新)
docker stats

# 查看指定容器(不刷新,輸出一次)
docker stats --no-stream app-api app-mysql app-redis

# 輸出示例:
# CONTAINER ID  NAME    CPU %  MEM USAGE / LIMIT  MEM %  NET I/O     BLOCK I/O    PIDS
# a1b2c3d4e5f6  app-api   2.35%  256MiB / 1GiB    25.00% 1.2GB / 800MB  50MB / 10MB   35
# b2c3d4e5f6a1  app-mysql  5.12%  1.1GiB / 2GiB    55.00% 500MB / 1.5GB  2GB / 500MB   42
# c3d4e5f6a1b2  app-redis  0.50%  50MiB / 768MiB   6.51%  200MB / 300MB  1MB / 5MB    5

5.2.2 cAdvisor + Prometheus + Grafana 監(jiān)控方案

生產(chǎn)環(huán)境推薦用 cAdvisor 采集容器指標(biāo),Prometheus 存儲(chǔ),Grafana 展示。

# 文件名:docker-compose.monitoring.yml

services:
cadvisor:
 image:gcr.io/cadvisor/cadvisor:v0.49.1
 container_name:cadvisor
 ports:
  -"8080:8080"
 volumes:
  -/:/rootfs:ro
  -/var/run:/var/run:ro
  -/sys:/sys:ro
  -/var/lib/docker/:/var/lib/docker:ro
  -/dev/disk/:/dev/disk:ro
 privileged:true
 restart:unless-stopped

prometheus:
 image:prom/prometheus:v2.51.0
 container_name:prometheus
 ports:
  -"9090:9090"
 volumes:
  -./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
  -prometheus-data:/prometheus
 command:
  -'--config.file=/etc/prometheus/prometheus.yml'
  -'--storage.tsdb.retention.time=30d'
 restart:unless-stopped

grafana:
 image:grafana/grafana:10.4.0
 container_name:grafana
 ports:
  -"3000:3000"
 volumes:
  -grafana-data:/var/lib/grafana
 environment:
  -GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD:-admin}
 restart:unless-stopped

volumes:
prometheus-data:
grafana-data:

Prometheus 采集配置:

# 文件路徑:prometheus/prometheus.yml
global:
scrape_interval:15s

scrape_configs:
-job_name:'cadvisor'
 static_configs:
  -targets:['cadvisor:8080']

5.2.3 監(jiān)控指標(biāo)說(shuō)明

指標(biāo)名稱 正常范圍 告警閾值 說(shuō)明
容器 CPU 使用率 < 70% of limit > 85% 持續(xù)高于 85% 需要擴(kuò)容或優(yōu)化
容器內(nèi)存使用率 < 80% of limit > 90% 接近限制值會(huì)觸發(fā) OOM
容器重啟次數(shù) 0 > 3 次/小時(shí) 頻繁重啟說(shuō)明應(yīng)用有問(wèn)題
磁盤(pán)使用率 < 70% > 85% Docker 數(shù)據(jù)目錄磁盤(pán)使用率
容器網(wǎng)絡(luò)錯(cuò)誤 0 > 0 網(wǎng)絡(luò)丟包或錯(cuò)誤需要排查

5.3 備份與恢復(fù)

5.3.1 備份策略

#!/bin/bash
# 文件名:docker-backup.sh
# Docker 數(shù)據(jù)備份腳本

BACKUP_DIR="/data/backups/docker"
DATE=$(date +%Y%m%d_%H%M%S)
RETENTION_DAYS=7

mkdir -p"$BACKUP_DIR"

echo"=== Docker 數(shù)據(jù)備份開(kāi)始:$DATE==="

# 備份所有命名卷
forvolin$(docker volume ls -q);do
 echo"備份卷:$vol"
  docker run --rm 
    -v"$vol":/source:ro 
    -v"$BACKUP_DIR":/backup 
    alpine tar czf"/backup/${vol}_${DATE}.tar.gz"-C /source.
done

# 備份 docker-compose 配置
echo"備份 Compose 配置..."
tar czf"$BACKUP_DIR/compose_configs_${DATE}.tar.gz"
  /opt/apps/*/docker-compose.yml 
  /opt/apps/*/.env 2>/dev/null

# 清理過(guò)期備份
find"$BACKUP_DIR"-name"*.tar.gz"-mtime +$RETENTION_DAYS-delete

echo"=== 備份完成 ==="

5.3.2 恢復(fù)流程

停止服務(wù):docker compose down

恢復(fù)卷數(shù)據(jù)

docker run --rm 
  -v mysql-data:/target 
  -v /data/backups/docker:/backup 
  alpine tar xzf /backup/mysql-data_20260207_030000.tar.gz -C /target

驗(yàn)證完整性:docker compose up -d && docker compose ps

檢查數(shù)據(jù):連接數(shù)據(jù)庫(kù)確認(rèn)數(shù)據(jù)完整

六、總結(jié)

6.1 技術(shù)要點(diǎn)回顧

安裝與配置:daemon.json 是 Docker 生產(chǎn)環(huán)境的核心配置,日志大小限制、live-restore、網(wǎng)段規(guī)劃這三項(xiàng)必須配置,否則遲早出事故

Dockerfile 編寫(xiě):多階段構(gòu)建是鏡像瘦身的關(guān)鍵手段,Go 應(yīng)用從 1.3GB 壓縮到 15MB,Java 應(yīng)用從 900MB 壓縮到 180MB。.dockerignore 必須有,防止敏感文件打進(jìn)鏡像

Compose 編排:healthcheck + depends_on condition 控制啟動(dòng)順序,deploy.resources 限制資源,networks 隔離前后端流量

安全加固:非 root 運(yùn)行、只讀文件系統(tǒng)、drop capabilities、Trivy 鏡像掃描,四道防線缺一不可

監(jiān)控與運(yùn)維:docker stats 日常巡檢,cAdvisor + Prometheus + Grafana 長(zhǎng)期監(jiān)控,定期 docker system prune 清理空間

6.2 進(jìn)階學(xué)習(xí)方向

Kubernetes 容器編排:Docker 解決了單機(jī)容器化問(wèn)題,K8s 解決多機(jī)編排問(wèn)題。掌握 Docker 后學(xué) K8s 是自然的進(jìn)階路徑

學(xué)習(xí)資源:Kubernetes 官方文檔

實(shí)踐建議:先用 kind 或 minikube 搭建本地集群練手,再上生產(chǎn)

鏡像構(gòu)建優(yōu)化:深入 BuildKit 緩存機(jī)制、多平臺(tái)構(gòu)建、鏡像簽名和供應(yīng)鏈安全

學(xué)習(xí)資源:BuildKit 官方文檔

實(shí)踐建議:在 CI/CD 中實(shí)踐 BuildKit 緩存掛載,構(gòu)建速度能提升 50% 以上

容器運(yùn)行時(shí):了解 containerd、CRI-O 等底層運(yùn)行時(shí),理解 Docker 只是容器生態(tài)的上層工具

6.3 參考資料

Docker 官方文檔- 最權(quán)威的 Docker 使用參考

Dockerfile 最佳實(shí)踐- 官方推薦的 Dockerfile 編寫(xiě)規(guī)范

Docker Compose 規(guī)范- Compose 文件格式完整參考

Docker 安全基準(zhǔn)- CIS Docker Benchmark,安全加固檢查清單

Awesome Docker- Docker 生態(tài)工具和資源匯總

附錄

A. Docker 命令速查表

# 鏡像操作
docker images               # 列出本地鏡像
docker pull :         # 拉取鏡像
docker build -t : .      # 構(gòu)建鏡像
docker push :         # 推送鏡像
docker rmi             # 刪除鏡像
docker image prune -f           # 清理懸空鏡像
docker save -o backup.tar      # 導(dǎo)出鏡像為 tar
docker load -i backup.tar         # 從 tar 導(dǎo)入鏡像
docker tag         # 給鏡像打標(biāo)簽
dockerhistory          # 查看鏡像構(gòu)建歷史
# 容器操作
docker run -d --name      # 后臺(tái)運(yùn)行容器
docker ps                 # 查看運(yùn)行中的容器
docker ps -a               # 查看所有容器(含已停止)
docker stop           # 停止容器
docker start          # 啟動(dòng)已停止的容器
docker restart         # 重啟容器
docker rm            # 刪除容器
docker rm -f          # 強(qiáng)制刪除運(yùn)行中的容器
dockerexec-it  sh      # 進(jìn)入容器 shell
docker logs --tail 100 -f    # 查看容器日志
docker inspect         # 查看容器詳細(xì)信息
docker cp :/path /host/path  # 從容器復(fù)制文件到宿主機(jī)
docker stats               # 查看容器資源使用
docker top           # 查看容器內(nèi)進(jìn)程

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 測(cè)試
    +關(guān)注

    關(guān)注

    9

    文章

    6202

    瀏覽量

    131352
  • JAVA
    +關(guān)注

    關(guān)注

    20

    文章

    3001

    瀏覽量

    116422
  • 容器
    +關(guān)注

    關(guān)注

    0

    文章

    531

    瀏覽量

    22965
  • Docker
    +關(guān)注

    關(guān)注

    0

    文章

    532

    瀏覽量

    14243

原文標(biāo)題:Docker 容器化部署完全指南:從安裝到生產(chǎn)環(huán)境最佳實(shí)踐

文章出處:【微信號(hào):magedu-Linux,微信公眾號(hào):馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    如何使用 Docker容器技術(shù)

    對(duì)于開(kāi)發(fā)人員來(lái)說(shuō),Docker肯定都不陌生,今天小編帶大家重新學(xué)習(xí)一下Docker。 什么是 Docker 官話: Docker 是一種開(kāi)源的容器
    的頭像 發(fā)表于 09-30 11:24 ?1.7w次閱讀

    RK3568-Docker容器部署方法說(shuō)明

    RK3568-Docker容器部署方法說(shuō)明
    的頭像 發(fā)表于 01-22 10:12 ?2318次閱讀
    RK3568-<b class='flag-5'>Docker</b><b class='flag-5'>容器</b><b class='flag-5'>部署</b>方法說(shuō)明

    TLT507-Docker容器部署方法說(shuō)明

    TLT507-Docker容器部署方法說(shuō)明
    的頭像 發(fā)表于 01-26 09:49 ?1104次閱讀
    TLT507-<b class='flag-5'>Docker</b><b class='flag-5'>容器</b><b class='flag-5'>部署</b>方法說(shuō)明

    干貨分享 | RK3588 Ubuntu系統(tǒng)Docker容器使用指南

    前言:在瑞芯微RK3588高性能AIoT平臺(tái)上運(yùn)行Ubuntu系統(tǒng)時(shí),Docker容器技術(shù)能極大提升開(kāi)發(fā)部署效率。通過(guò)輕量級(jí)虛擬實(shí)現(xiàn)環(huán)境隔離與快速遷移,本文將從零開(kāi)始詳解RK3588
    的頭像 發(fā)表于 06-27 12:01 ?3855次閱讀
    干貨分享 | RK3588 Ubuntu系統(tǒng)<b class='flag-5'>Docker</b><b class='flag-5'>容器使用指南</b>

    ARM平臺(tái)實(shí)現(xiàn)Docker容器技術(shù)

    及依賴包到一個(gè)可移植的鏡像中,然后發(fā)布到任何流行的Linux或Windows機(jī)器上,亦可實(shí)現(xiàn)虛擬。容器完全使用沙箱機(jī)制,相互之間不會(huì)有任何接口。使用Docker,可像管理應(yīng)用程序一
    發(fā)表于 07-17 11:05

    ARM平臺(tái)實(shí)現(xiàn)Docker容器技術(shù)

    及依賴包到一個(gè)可移植的鏡像中,然后發(fā)布到任何流行的Linux或Windows機(jī)器上,亦可實(shí)現(xiàn)虛擬容器完全使用沙箱機(jī)制,相互之間不會(huì)有任何接口。使用Docker,可像管理應(yīng)用程序一
    發(fā)表于 07-25 14:36

    理解Docker容器并暢玩docker

    ,完全不影響其他容器的正常運(yùn)作)。這樣描述,還是不大明白,我們可以實(shí)際操作一下。先打開(kāi)兩個(gè)命令行,在其中一個(gè)命令行執(zhí)行以下命令:docker run -it --name a1_rm alpine命令解析
    發(fā)表于 11-05 09:54

    Docker入門(mén)指南

    ?簡(jiǎn)化Arm硬件的應(yīng)用程序開(kāi)發(fā)?在開(kāi)始之前在云中工作并在邊緣部署指南假設(shè)您熟悉容器概念。如果你不熟悉容器的概念,你可以在Docker入門(mén)中
    發(fā)表于 08-02 06:09

    Docker容器部署-以TI AM335x平臺(tái)為例

    前言:Docker是一個(gè)開(kāi)源的應(yīng)用容器引擎,讓開(kāi)發(fā)者可打包他們的應(yīng)用以及依賴包到一個(gè)可移植的鏡像中,然后發(fā)布到任何流行的Linux或Windows機(jī)器上,亦可實(shí)現(xiàn)虛擬容器
    的頭像 發(fā)表于 12-20 15:16 ?2157次閱讀
    <b class='flag-5'>Docker</b><b class='flag-5'>容器</b><b class='flag-5'>部署</b>-以TI AM335x平臺(tái)為例

    docker部署mysql的壞處

    Docker 是一種虛擬技術(shù),它允許開(kāi)發(fā)人員在容器內(nèi)打包應(yīng)用程序及其所有依賴項(xiàng),從而實(shí)現(xiàn)在不同環(huán)境中運(yùn)行相同的應(yīng)用程序的能力。然而,在使用 Docker
    的頭像 發(fā)表于 11-23 09:29 ?2313次閱讀

    docker部署對(duì)性能的影響

    Docker 是一個(gè)流行的容器平臺(tái),它提供了一種輕量級(jí)的虛擬技術(shù),使得應(yīng)用程序可以在獨(dú)立的容器中運(yùn)行。然而,
    的頭像 發(fā)表于 11-23 09:31 ?2934次閱讀

    docker容器有幾種狀態(tài)

    Docker 是一種流行的容器平臺(tái),它能夠幫助開(kāi)發(fā)人員將應(yīng)用程序和其依賴打包成一個(gè)獨(dú)立的容器,并且能夠在不同的環(huán)境中進(jìn)行部署和運(yùn)行。在
    的頭像 發(fā)表于 11-23 09:50 ?3805次閱讀

    ARM平臺(tái)實(shí)現(xiàn)Docker容器技術(shù)

    ,亦可實(shí)現(xiàn)虛擬。容器完全使用沙箱機(jī)制,相互之間不會(huì)有任何接口。使用Docker,可像管理應(yīng)用程序一樣管理基礎(chǔ)結(jié)構(gòu)。通過(guò)利用Docker
    的頭像 發(fā)表于 03-07 13:48 ?1659次閱讀
    ARM平臺(tái)實(shí)現(xiàn)<b class='flag-5'>Docker</b><b class='flag-5'>容器</b>技術(shù)

    基于 Docker 與 Jenkins 實(shí)現(xiàn)自動(dòng)部署

    優(yōu)化,為 Docker 容器應(yīng)用與 Jenkins 自動(dòng)流水線提供了理想的運(yùn)行環(huán)境。無(wú)論是快速構(gòu)建、測(cè)試還是部署,F(xiàn)lexus X 都能
    的頭像 發(fā)表于 01-07 17:25 ?1027次閱讀
    基于 <b class='flag-5'>Docker</b> 與 Jenkins 實(shí)現(xiàn)自動(dòng)<b class='flag-5'>化</b><b class='flag-5'>部署</b>

    如何使用Docker部署大模型

    隨著深度學(xué)習(xí)和大模型的快速發(fā)展,如何高效地部署這些模型成為了一個(gè)重要的挑戰(zhàn)。Docker 作為一種輕量級(jí)的容器技術(shù),能夠?qū)⒛P图捌湟蕾嚟h(huán)境打包成一個(gè)可移植的
    的頭像 發(fā)表于 05-24 16:39 ?1113次閱讀