1. Shell与Docker自动化实践全景
在现代化运维和DevOps实践中,Shell脚本与Docker的组合堪称效率提升的黄金搭档。这种组合特别适合需要频繁进行容器生命周期管理、批量操作和标准化构建的场景。通过Shell脚本封装Docker命令,我们能够将复杂的容器操作流程转化为可重复执行的一键式操作,这在持续集成、测试环境管理和生产部署中展现出巨大价值。
我曾在一个分布式系统的部署项目中,通过编写约200行的Shell脚本集,将原本需要人工操作2小时的部署流程缩短到8分钟完成。这种效率提升不仅减少了人为错误,更重要的是让团队能够将精力集中在更有价值的业务逻辑开发上。下面我将分享这种自动化实践的核心要点和具体实现方案。
2. 容器生命周期管理自动化
2.1 智能容器启停控制
容器启停是日常操作中最频繁的需求,一个健壮的启停脚本需要考虑状态检查、异常处理和日志记录。以下是经过生产验证的脚本模板:
bash复制#!/bin/bash
CONTAINER_NAME="app-service"
TIMEOUT=30
stop_container() {
echo "Checking container status..."
if [ "$(docker ps -q -f name=$CONTAINER_NAME)" ]; then
echo "Stopping running container..."
docker stop $CONTAINER_NAME > /dev/null 2>&1
# 等待容器完全停止
local counter=0
while [ "$(docker inspect -f '{{.State.Running}}' $CONTAINER_NAME 2>/dev/null)" == "true" ]; do
sleep 1
counter=$((counter + 1))
if [ $counter -ge $TIMEOUT ]; then
echo "Error: Timeout waiting for container to stop"
exit 1
fi
done
echo "Container stopped successfully"
else
echo "Container not running, skipping stop"
fi
}
start_container() {
if [ ! "$(docker ps -q -f name=$CONTAINER_NAME)" ]; then
echo "Starting container..."
docker start $CONTAINER_NAME > /dev/null 2>&1
# 健康检查
counter=0
while [ "$(docker inspect -f '{{.State.Health.Status}}' $CONTAINER_NAME 2>/dev/null)" != "healthy" ]; do
sleep 2
counter=$((counter + 2))
if [ $counter -ge $TIMEOUT ]; then
echo "Warning: Container started but health check timeout"
break
fi
done
echo "Container started and healthy"
else
echo "Container already running"
fi
}
case "$1" in
start)
start_container
;;
stop)
stop_container
;;
restart)
stop_container
start_container
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
esac
关键改进点:
- 增加了容器状态双重检查机制,避免误操作
- 引入超时控制防止脚本挂死
- 集成健康检查确保服务可用性
- 完善的日志输出便于问题排查
2.2 多容器编排管理
当需要管理多个关联容器时,推荐使用docker-compose结合Shell脚本的方案:
bash复制#!/bin/bash
COMPOSE_FILE="docker-compose-cluster.yml"
validate_environment() {
required_vars=("DB_PASSWORD" "API_KEY")
for var in "${required_vars[@]}"; do
if [ -z "${!var}" ]; then
echo "Error: Environment variable $var not set"
exit 1
fi
done
}
cluster_up() {
validate_environment
docker-compose -f $COMPOSE_FILE up -d --scale web=3 --scale worker=2
docker-compose -f $COMPOSE_FILE ps
}
cluster_down() {
docker-compose -f $COMPOSE_FILE down --volumes --remove-orphans
}
case "$1" in
up)
cluster_up
;;
down)
cluster_down
;;
*)
echo "Usage: $0 {up|down}"
exit 1
esac
重要提示:生产环境使用时应添加资源限制检查,避免容器过度占用系统资源。可通过
docker stats命令实时监控。
3. 镜像构建流水线优化
3.1 智能镜像构建脚本
标准化的镜像构建流程应该包含版本管理、缓存清理和构建验证:
bash复制#!/bin/bash
IMAGE_NAME="app-service"
VERSION=$(date +%Y%m%d_%H%M%S)
BUILD_DIR="build_${VERSION}"
DOCKERFILE="Dockerfile.prod"
prepare_build() {
mkdir -p $BUILD_DIR
cp -r src/ config/ $DOCKERFILE $BUILD_DIR/
# 注入构建时环境变量
echo "BUILD_VERSION=${VERSION}" >> $BUILD_DIR/.build-env
}
build_image() {
echo "Building image ${IMAGE_NAME}:${VERSION}"
docker build \
-f $BUILD_DIR/$DOCKERFILE \
-t $IMAGE_NAME:$VERSION \
-t $IMAGE_NAME:latest \
--build-arg BUILDKIT_INLINE_CACHE=1 \
$BUILD_DIR
# 验证镜像大小
local size=$(docker inspect $IMAGE_NAME:$VERSION --format='{{.Size}}')
if [ $size -gt 500000000 ]; then
echo "Warning: Image size exceeds 500MB (actual: $((size/1000000))MB)"
fi
}
cleanup() {
# 保留最近5个构建目录
ls -td build_* | tail -n +6 | xargs rm -rf
# 清理悬空镜像
docker image prune -f
}
prepare_build
build_image
cleanup
构建优化技巧:
- 使用时间戳作为版本号确保唯一性
- 分离构建目录避免污染源代码
- 启用BuildKit缓存提升后续构建速度
- 自动清理机制防止磁盘空间耗尽
3.2 多阶段构建实践
对于复杂应用的镜像构建,推荐采用多阶段构建方案:
dockerfile复制# Dockerfile.multi-stage
FROM node:16 as builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
对应的构建脚本应增加构建参数控制:
bash复制#!/bin/bash
# build-multi-stage.sh
select_stage() {
case "$1" in
dev)
DOCKERFILE="Dockerfile.dev"
TARGET="development"
;;
prod)
DOCKERFILE="Dockerfile.multi-stage"
TARGET="builder"
;;
*)
echo "Unknown stage: $1"
exit 1
esac
}
select_stage $1
docker build \
-f $DOCKERFILE \
--target $TARGET \
-t app-image:$1 \
.
4. 批量部署架构设计
4.1 多主机容器部署方案
跨主机的批量部署需要考虑SSH连接管理、文件传输和并行控制:
bash复制#!/bin/bash
# deploy-cluster.sh
HOSTS=("web1.example.com" "web2.example.com" "worker1.example.com")
IMAGE_VERSION="20230815_1"
DEPLOY_USER="deployer"
CONFIG_DIR="configs"
deploy_host() {
local host=$1
echo "Deploying to $host"
# 传输必要文件
rsync -azP --delete \
$CONFIG_DIR/ \
$DEPLOY_USER@$host:/opt/app/config/
# 远程执行命令
ssh $DEPLOY_USER@$host <<EOF
docker pull registry.example.com/app:$IMAGE_VERSION
docker stop app || true
docker rm app || true
docker run -d \
--name app \
-v /opt/app/config:/config \
-p 8080:8080 \
registry.example.com/app:$IMAGE_VERSION
EOF
}
# 并行部署(限制最大并发数)
MAX_CONCURRENT=2
for host in "${HOSTS[@]}"; do
((i=i%MAX_CONCURRENT)); ((i++==0)) && wait
deploy_host $host &
done
wait
echo "All hosts deployed"
关键安全措施:
- 使用SSH密钥认证而非密码
- 限制rsync的删除权限
- 控制并行度避免过载
- 完善的错误处理机制
4.2 蓝绿部署实现
实现零宕期的蓝绿部署方案:
bash复制#!/bin/bash
# blue-green-deploy.sh
CURRENT_COLOR=$(docker network inspect app-network --format='{{.Labels.color}}')
if [ "$CURRENT_COLOR" == "blue" ]; then
NEW_COLOR="green"
else
NEW_COLOR="blue"
fi
# 启动新版本容器
docker run -d \
--name app-$NEW_COLOR \
--network app-network \
--label color=$NEW_COLOR \
-p ${NEW_COLOR}8080:8080 \
app:$IMAGE_VERSION
# 等待新容器就绪
while ! curl -sIf http://localhost:${NEW_COLOR}8080/health; do
sleep 5
done
# 切换流量
docker service update \
--update-failure-action rollback \
--update-parallelism 1 \
--update-delay 10s \
--detach=false \
--label-add color=$NEW_COLOR \
app-service
# 下线旧版本
docker stop app-$CURRENT_COLOR
docker rm app-$CURRENT_COLOR
echo "Deployment switched to $NEW_COLOR"
5. 实战问题排查手册
5.1 常见错误与解决方案
| 错误现象 | 可能原因 | 解决方案 |
|---|---|---|
| 容器启动后立即退出 | 主进程退出/启动命令错误 | 检查docker logs;确保CMD命令前台运行 |
| 端口冲突 | 主机端口已被占用 | 使用netstat -tulnp确认;修改映射端口 |
| 磁盘空间不足 | 过多悬空镜像/卷 | 定期执行docker system prune |
| 网络连接失败 | 防火墙规则限制 | 检查iptables/nftables规则 |
| 镜像拉取失败 | 认证问题/仓库不可达 | 配置docker login;检查网络连通性 |
5.2 性能调优技巧
- 容器内存限制:通过
-m 512m限制内存,避免单个容器耗尽系统资源 - IO优化:对数据库类容器使用
--mount替代-v获得更好性能 - CPU约束:使用
--cpus 1.5限制CPU使用量 - 日志轮转:配置
--log-opt max-size=10m防止日志文件过大 - 健康检查:合理设置
--health-interval避免检查过于频繁
bash复制# 生产环境推荐参数示例
docker run -d \
--name mysql-prod \
-m 2g \
--cpus 2 \
--mount type=volume,source=mysql-data,target=/var/lib/mysql \
--log-opt max-size=10m \
--log-opt max-file=3 \
--health-cmd="mysqladmin ping" \
--health-interval=30s \
--health-timeout=5s \
mysql:5.7
6. 进阶自动化架构
6.1 自愈系统实现
通过监控+自动化实现容器自愈:
bash复制#!/bin/bash
# self-healing.sh
MONITOR_INTERVAL=60
CONTAINER_NAME="critical-service"
monitor_container() {
while true; do
if ! docker inspect $CONTAINER_NAME &>/dev/null; then
echo "$(date) - Container missing, restarting..."
docker start $CONTAINER_NAME
elif [ "$(docker inspect -f '{{.State.Status}}' $CONTAINER_NAME)" != "running" ]; then
echo "$(date) - Container not running, restarting..."
docker restart $CONTAINER_NAME
fi
sleep $MONITOR_INTERVAL
done
}
# 启动监控
monitor_container
6.2 版本回滚机制
实现带版本记录的自动化回滚:
bash复制#!/bin/bash
# rollback.sh
VERSIONS=($(docker images --filter=reference="app:*" --format "{{.Tag}}" | sort -r))
CURRENT_VERSION=$(docker inspect app --format='{{.Config.Image}}' | cut -d: -f2)
echo "Available versions:"
for i in "${!VERSIONS[@]}"; do
echo "[$i] ${VERSIONS[$i]}"
done
read -p "Select version to rollback (current: $CURRENT_VERSION): " selection
if [[ $selection -ge 0 && $selection -lt ${#VERSIONS[@]} ]]; then
echo "Rolling back to ${VERSIONS[$selection]}"
docker stop app
docker rm app
docker run -d \
--name app \
-p 8080:8080 \
app:${VERSIONS[$selection]}
else
echo "Invalid selection"
exit 1
fi
7. 安全加固实践
7.1 容器安全基线
-
非root用户运行:
dockerfile复制FROM alpine RUN adduser -D appuser USER appuser -
只读文件系统:
bash复制
docker run --read-only -v /tmp:/tmp app -
能力限制:
bash复制
docker run --cap-drop ALL --cap-add NET_BIND_SERVICE app -
资源隔离:
bash复制
docker run --security-opt no-new-privileges app
7.2 镜像扫描集成
在CI流水线中集成安全扫描:
bash复制#!/bin/bash
# scan-image.sh
IMAGE=$1
TRIVY_CACHE_DIR="/tmp/trivy-cache"
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
-v $TRIVY_CACHE_DIR:/root/.cache/ \
aquasec/trivy \
--exit-code 1 \
--severity CRITICAL \
--ignore-unfixed \
$IMAGE
if [ $? -eq 0 ]; then
echo "Scan passed, no critical vulnerabilities"
else
echo "Critical vulnerabilities found!"
exit 1
fi
8. 监控与日志体系
8.1 容器指标收集
使用cAdvisor+Prometheus实现监控:
bash复制#!/bin/bash
# setup-monitoring.sh
# 启动cAdvisor
docker run -d \
--name=cadvisor \
--volume=/:/rootfs:ro \
--volume=/var/run:/var/run:ro \
--volume=/sys:/sys:ro \
--volume=/var/lib/docker/:/var/lib/docker:ro \
--publish=8081:8080 \
google/cadvisor
# 启动Prometheus
docker run -d \
--name=prometheus \
-p 9090:9090 \
-v prometheus.yml:/etc/prometheus/prometheus.yml \
prom/prometheus
8.2 集中式日志管理
ELK方案配置示例:
bash复制#!/bin/bash
# setup-logging.sh
# Elasticsearch
docker run -d \
--name elasticsearch \
-p 9200:9200 \
-e "discovery.type=single-node" \
docker.elastic.co/elasticsearch/elasticsearch:7.12.0
# Logstash
docker run -d \
--name logstash \
-v logstash.conf:/usr/share/logstash/pipeline/logstash.conf \
docker.elastic.co/logstash/logstash:7.12.0
# Kibana
docker run -d \
--name kibana \
-p 5601:5601 \
docker.elastic.co/kibana/kibana:7.12.0
容器日志驱动配置:
bash复制docker run \
--log-driver=syslog \
--log-opt syslog-address=tcp://logstash:514 \
app
9. 持续集成流水线集成
9.1 GitLab CI集成示例
.gitlab-ci.yml配置:
yaml复制stages:
- build
- test
- deploy
build_image:
stage: build
script:
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
rules:
- if: $CI_COMMIT_BRANCH == "main"
run_tests:
stage: test
script:
- docker run --rm $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA npm test
deploy_staging:
stage: deploy
script:
- echo "Deploying to staging"
- scp deploy.sh user@staging:/tmp/
- ssh user@staging "bash /tmp/deploy.sh $CI_COMMIT_SHA"
environment:
name: staging
when: manual
9.2 Jenkins Pipeline实现
Jenkinsfile示例:
groovy复制pipeline {
agent any
environment {
DOCKER_REGISTRY = 'registry.example.com'
}
stages {
stage('Build') {
steps {
script {
docker.build("${DOCKER_REGISTRY}/app:${env.BUILD_ID}")
}
}
}
stage('Test') {
steps {
script {
docker.image("${DOCKER_REGISTRY}/app:${env.BUILD_ID}").inside {
sh 'npm run test'
}
}
}
}
stage('Deploy') {
when {
branch 'production'
}
steps {
sshagent(['deploy-key']) {
sh """
scp deploy.sh user@production:/tmp/
ssh user@production "/tmp/deploy.sh ${env.BUILD_ID}"
"""
}
}
}
}
}
10. 多环境配置管理
10.1 环境差异化配置
使用envsubst实现模板化配置:
bash复制#!/bin/bash
# generate-config.sh
ENVIRONMENT=$1
CONFIG_TEMPLATE="config.template"
OUTPUT_FILE="config.${ENVIRONMENT}.json"
export DB_HOST="db-${ENVIRONMENT}.example.com"
export LOG_LEVEL=$([ "$ENVIRONMENT" == "prod" ] && echo "WARN" || echo "DEBUG")
envsubst < $CONFIG_TEMPLATE > $OUTPUT_FILE
echo "Generated $OUTPUT_FILE for $ENVIRONMENT"
10.2 容器配置注入
运行时配置注入方案:
bash复制#!/bin/bash
# start-with-config.sh
ENV_FILE="config.env"
SECRETS_FILE="/run/secrets/db_password"
docker run -d \
--name app \
--env-file $ENV_FILE \
--mount type=bind,source=$SECRETS_FILE,target=/etc/secrets/db_password \
app-image
对应的Dockerfile配置:
dockerfile复制FROM alpine
COPY entrypoint.sh /
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
entrypoint.sh示例:
bash复制#!/bin/sh
# 从环境变量和secret文件生成最终配置
echo "Generating runtime config..."
cat > /app/config.json <<EOF
{
"db": {
"host": "${DB_HOST}",
"password": "$(cat /etc/secrets/db_password)"
}
}
EOF
exec "$@"
11. 性能基准测试方案
11.1 容器性能测试
使用stress-ng进行资源测试:
bash复制#!/bin/bash
# benchmark.sh
docker run -it --rm \
--cpus 2 \
-m 1g \
ubuntu \
bash -c "apt-get update && apt-get install -y stress-ng && \
stress-ng --cpu 4 --io 2 --vm 1 --vm-bytes 500M --timeout 60s --metrics"
11.2 网络性能测试
容器间网络基准测试:
bash复制# 启动iperf3服务端
docker run -d --name iperf-server \
-p 5201:5201 \
networkstatic/iperf3 -s
# 运行客户端测试
docker run -it --rm \
networkstatic/iperf3 -c iperf-server -t 30 -P 4
12. 备份与恢复策略
12.1 容器状态备份
完整容器备份方案:
bash复制#!/bin/bash
# backup-container.sh
CONTAINER_NAME="mysql-prod"
BACKUP_DIR="/backups"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
# 停止容器确保一致性
docker stop $CONTAINER_NAME
# 备份数据卷
docker run --rm \
-v $BACKUP_DIR:/backup \
-v mysql_data:/volume \
alpine \
tar czf /backup/mysql_data_$TIMESTAMP.tar.gz -C /volume .
# 备份容器配置
docker inspect $CONTAINER_NAME > $BACKUP_DIR/${CONTAINER_NAME}_inspect_$TIMESTAMP.json
# 重新启动容器
docker start $CONTAINER_NAME
# 保留最近7天备份
find $BACKUP_DIR -type f -name '*.tar.gz' -mtime +7 -delete
12.2 镜像仓库备份
私有仓库备份脚本:
bash复制#!/bin/bash
# backup-registry.sh
REGISTRY_CONTAINER="registry"
BACKUP_DIR="/backups/registry"
TIMESTAMP=$(date +%Y%m%d)
# 创建备份目录
mkdir -p $BACKUP_DIR/$TIMESTAMP
# 导出仓库数据
docker exec $REGISTRY_CONTAINER \
registry garbage-collect /etc/docker/registry/config.yml --delete-untagged=true
docker cp $REGISTRY_CONTAINER:/var/lib/registry $BACKUP_DIR/$TIMESTAMP
# 压缩备份
tar czf $BACKUP_DIR/registry_$TIMESTAMP.tar.gz -C $BACKUP_DIR/$TIMESTAMP registry
# 清理临时文件
rm -rf $BACKUP_DIR/$TIMESTAMP
13. 容器网络进阶配置
13.1 自定义网络隔离
创建隔离网络并配置防火墙规则:
bash复制#!/bin/bash
# setup-network.sh
# 创建自定义网络
docker network create \
--driver bridge \
--subnet 172.28.0.0/16 \
--gateway 172.28.0.1 \
--opt com.docker.network.bridge.name=isolated \
isolated-net
# 配置iptables规则
sudo iptables -I DOCKER-USER -i isolated -o eth0 -j DROP
sudo iptables -I DOCKER-USER -i eth0 -o isolated -j REJECT
# 启动容器使用该网络
docker run -d \
--name secured-app \
--network isolated-net \
-p 8080:8080 \
app-image
13.2 多主机网络方案
使用Overlay网络实现跨主机通信:
bash复制# 初始化Swarm
docker swarm init
# 创建Overlay网络
docker network create \
--driver overlay \
--subnet 10.0.9.0/24 \
--opt encrypted=true \
cluster-net
# 在服务中使用该网络
docker service create \
--name app-service \
--network cluster-net \
--replicas 3 \
app-image
14. 资源配额与限制
14.1 容器资源限制
全面的资源限制配置:
bash复制#!/bin/bash
# start-with-limits.sh
docker run -d \
--name resource-limited \
--cpus 1.5 \
--memory 2g \
--memory-swap 3g \
--blkio-weight 500 \
--device-read-bps /dev/sda:1mb \
--device-write-iops /dev/sdb:1000 \
--pids-limit 200 \
app-image
14.2 资源使用监控
实时资源监控脚本:
bash复制#!/bin/bash
# monitor-resources.sh
CONTAINER_NAME=$1
INTERVAL=5
while true; do
clear
docker stats $CONTAINER_NAME --no-stream --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}\t{{.BlockIO}}"
sleep $INTERVAL
done
15. 容器安全扫描与审计
15.1 镜像漏洞扫描
定期扫描镜像漏洞:
bash复制#!/bin/bash
# scan-images.sh
IMAGES=$(docker images --format "{{.Repository}}:{{.Tag}}")
for image in $IMAGES; do
echo "Scanning $image..."
docker scan --file Dockerfile $image
# 检查高危漏洞
if docker scan $image | grep -q "CRITICAL"; then
echo "CRITICAL vulnerabilities found in $image"
exit 1
fi
done
15.2 容器配置审计
使用docker-bench-security进行安全审计:
bash复制#!/bin/bash
# security-audit.sh
docker run -it --net host --pid host --userns host --cap-add audit_control \
-v /var/lib:/var/lib \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /usr/lib/systemd:/usr/lib/systemd \
-v /etc:/etc \
--label docker_bench_security \
docker/docker-bench-security
16. 容器化开发环境
16.1 开发容器配置
VSCode开发容器示例:
dockerfile复制# Dockerfile.dev
FROM node:16
# 安装开发工具
RUN apt-get update && apt-get install -y \
git \
zsh \
curl
# 创建非root用户
ARG USERNAME=developer
ARG USER_UID=1000
ARG USER_GID=$USER_UID
RUN groupadd --gid $USER_GID $USERNAME \
&& useradd --uid $USER_UID --gid $USER_GID -m $USERNAME \
&& apt-get install -y sudo \
&& echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \
&& chmod 0440 /etc/sudoers.d/$USERNAME
USER $USERNAME
# 安装开发环境
RUN sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
16.2 开发环境启动脚本
bash复制#!/bin/bash
# start-dev.sh
docker build -t dev-env -f Dockerfile.dev .
docker run -it --rm \
-v $(pwd):/workspace \
-v /var/run/docker.sock:/var/run/docker.sock \
-p 3000:3000 \
-p 9229:9229 \
--name dev-container \
dev-env \
zsh
17. 容器日志管理进阶
17.1 结构化日志处理
配置JSON格式日志:
bash复制docker run -d \
--name log-producer \
--log-driver=json-file \
--log-opt tag="{{.Name}}/{{.ID}}" \
--log-opt labels=production \
--log-opt env=TIER \
--log-opt max-size=10m \
--log-opt max-file=3 \
app-image
17.2 日志过滤与处理
使用Fluentd处理容器日志:
bash复制# fluentd.conf
<source>
@type forward
port 24224
</source>
<filter docker.**>
@type grep
<regexp>
key log
pattern /ERROR|WARN/
</regexp>
</filter>
<match docker.**>
@type elasticsearch
host elasticsearch
port 9200
logstash_format true
</match>
启动Fluentd容器:
bash复制docker run -d \
--name fluentd \
-p 24224:24224 \
-v fluentd.conf:/fluentd/etc/fluent.conf \
fluent/fluentd
18. 容器存储优化
18.1 存储驱动选择
根据工作负载选择合适的存储驱动:
bash复制# 查看当前存储驱动
docker info --format '{{.Driver}}'
# 修改存储驱动(需在/etc/docker/daemon.json配置)
{
"storage-driver": "overlay2",
"storage-opts": [
"overlay2.override_kernel_check=true"
]
}
18.2 卷管理最佳实践
使用命名卷并设置适当权限:
bash复制#!/bin/bash
# setup-data-volume.sh
VOLUME_NAME="app-data"
# 创建卷并设置权限
docker volume create $VOLUME_NAME
docker run --rm -v $VOLUME_NAME:/data alpine \
chown -R 1000:1000 /data
# 使用卷启动容器
docker run -d \
--name app-with-data \
-v $VOLUME_NAME:/app/data \
-e "UID=1000" \
-e "GID=1000" \
app-image
19. 容器编排进阶技巧
19.1 服务更新策略
蓝绿部署与金丝雀发布:
bash复制# 金丝雀发布示例
docker service update \
--image app:new-version \
--update-parallelism 1 \
--update-delay 30s \
--update-failure-action pause \
app-service
19.2 资源约束与服务放置
约束服务运行位置:
bash复制docker service create \
--name constrained-service \
--constraint node.role==worker \
--placement-pref 'spread=node.labels.az' \
--reserve-cpu 1 \
--reserve-memory 512m \
app-image
20. 跨平台构建方案
20.1 多架构镜像构建
使用buildx构建多平台镜像:
bash复制#!/bin/bash
# build-multi-arch.sh
docker buildx create --use
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t username/app:multi-arch \
--push .
20.2 构建缓存优化
利用缓存加速构建:
dockerfile复制# Dockerfile.cache
FROM node:16 as builder
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
RUN npm run build
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
构建命令:
bash复制docker build \
--cache-from=username/app:cache \
-t username/app:latest \
-f Dockerfile.cache .