我的个人博客

🐳 Docker 学习笔记

返回首页
技术分享 2025-12-20

🎯 学习目标

通过本笔记掌握Docker的核心概念、常用命令和实际应用场景,提升容器化部署能力。


📖 简介

Docker是一个开源的容器化平台,让开发者能够打包应用及其依赖包到一个可移植的容器中。

🔗 相关链接


🚀 安装配置

基础安装

apt install docker.io

配置镜像加速器

tee /etc/docker/daemon.json <<-'EOF'
{
    "registry-mirrors": [
     "https://docker.m.daocloud.io",
     "https://docker.imgdb.de",
     "https://docker-0.unsee.tech",
     "https://docker.hlmirror.com",
     "https://docker.1ms.run",
     "https://func.ink",
     "https://lispy.org",
     "https://docker.xiaogenban1993.com"
    ]
}
EOF

重启Docker服务

systemctl daemon-reload
systemctl restart docker

⚡ 常用命令

📦 镜像相关命令

🔍 查看镜像

docker images

输出说明:

  • REPOSITORY:镜像名称
  • TAG:镜像标签
  • IMAGE ID:镜像ID
  • CREATED:镜像的创建日期
  • SIZE:镜像大小

🔎 搜索镜像

docker search 镜像名称

输出说明:

  • NAME:仓库名称
  • DESCRIPTION:镜像描述
  • STARS:下载数量
  • OFFICAL:是否官方
  • AUTOMATED:自动构建

⬇️ 拉取镜像

docker pull 镜像名称

🗑️ 删除镜像

# 删除单个镜像
docker rmi 镜像ID

# 删除所有镜像
docker rmi `docker images -q`

🏗️ 容器相关命令

👀 查看容器

# 查看正在运行的容器
docker ps

# 查看全部容器
docker ps -a

# 查看最后一次运行的容器
docker ps -f status=exited

▶️ 启动容器

docker run [参数] 镜像名:标签 [命令]

常用参数:

  • -i:表示运行容器
  • -t:表示进入命令行
  • --name:为创建的容器命名
  • -d:守护式容器(后台运行)
  • -p:映射端口

示例:

# 交互式启动容器
docker run -it --name=centos centos:7 /bin/bash

# 守护式启动容器
docker run -di --name=centos centos:7

# 进入守护式容器
docker exec -it 容器名称 /bin/bash

🔄 容器管理

# 停止容器
docker stop 容器名/容器ID

# 启动容器
docker start 容器名/容器ID

# 退出容器
exit

📁 文件传输

# 从主机复制文件到容器
docker cp 文件路径 容器ID/名称:容器内路径

# 从容器复制文件到主机
docker cp 容器ID/名称:容器内路径 主机路径

📂 目录挂载

docker run -di -v 主机目录:容器目录 --name=容器名称 镜像名

示例:

docker run -di -v /usr/local/test:/usr/local/test --name=test centos:7

🗑️ 删除容器

docker rm 容器ID/容器名称

🌐 应用部署实战

🗄️ MySQL部署

# 拉取MySQL镜像
docker pull mysql:5.7

# 启动MySQL容器
docker run -di --name=mysql \
  -p 3306:3306 \
  -e MYSQL_ROOT_PASSWORD=toor \
  mysql:5.7

🌍 Nginx部署

# 拉取Nginx镜像
docker pull nginx

# 启动Nginx容器
docker run -di --name=nginx -p 80:80 nginx

# 带配置文件挂载的Nginx
docker run -di --name=nginx \
  -p 80:80 \
  -v /usr/local/nginx:/etc/nginx \
  nginx

🔴 Redis部署

# 拉取Redis镜像
docker pull redis

# 启动Redis容器
docker run -di --name=redis -p 6379:6379 redis

🐰 RabbitMQ部署

# 拉取RabbitMQ镜像
docker pull rabbitmq:3.7.12

# 启动RabbitMQ容器
docker run -di --name=rabbitmq \
  -p 5671:5671 \
  -p 5672:5672 \
  -p 4369:4369 \
  -p 25672:25672 \
  -p 15671:15671 \
  -p 15672:15672 \
  rabbitmq:3.7.12

# 进入容器启用管理插件
docker exec -it rabbitmq /bin/bash
rabbitmq-plugins enable rabbitmq_management

💾 备份与迁移

📦 容器保存为镜像

# 将容器保存为新镜像
docker commit 容器名 新镜像名

# 导出镜像到文件
docker save -o 镜像名.tar 镜像名

# 从文件导入镜像
docker load -i 镜像名.tar

📝 Dockerfile

Dockerfile是一个文本文件,包含了一系列指令,用于自动构建Docker镜像。

🏗️ 基本语法

# 基础镜像
FROM 镜像名:标签

# 维护者信息
MAINTAINER 作者 <邮箱>

# 设置工作目录
WORKDIR /app

# 复制文件
COPY 源路径 目标路径

# 添加文件(支持解压)
ADD 源文件 目标路径

# 运行命令
RUN 命令

# 设置环境变量
ENV 键=值

# 暴露端口
EXPOSE 端口号

# 容器启动命令
CMD ["命令", "参数1", "参数2"]

# 入口点
ENTRYPOINT ["命令", "参数1"]

📋 常用指令详解

FROM - 基础镜像

FROM ubuntu:20.04
FROM node:16-alpine

WORKDIR - 工作目录

WORKDIR /app
# 相当于 cd /app

COPY vs ADD

# COPY - 简单复制文件
COPY ./app.js /app/
COPY ./package*.json ./

# ADD - 支持URL和解压
ADD https://example.com/file.tar.gz /tmp/
ADD app.tar.gz /app/  # 自动解压

RUN - 执行命令

RUN apt-get update && apt-get install -y \
    curl \
    vim \
    && rm -rf /var/lib/apt/lists/*

RUN npm install

ENV - 环境变量

ENV NODE_ENV=production
ENV APP_VERSION=1.0.0

EXPOSE - 暴露端口

EXPOSE 3000
EXPOSE 8080

CMD vs ENTRYPOINT

# CMD - 可以被docker run覆盖
CMD ["node", "app.js"]

# ENTRYPOINT - 固定入口点
ENTRYPOINT ["node"]
CMD ["app.js"]  # 作为ENTRYPOINT的参数

🎯 实战示例

Node.js应用Dockerfile

FROM node:16-alpine

# 设置工作目录
WORKDIR /app

# 复制package文件
COPY package*.json ./

# 安装依赖
RUN npm ci --only=production

# 复制应用代码
COPY . .

# 创建非root用户
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nodejs -u 1001

# 更改文件所有者
RUN chown -R nodejs:nodejs /app
USER nodejs

# 暴露端口
EXPOSE 3000

# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD curl -f http://localhost:3000/health || exit 1

# 启动应用
CMD ["node", "app.js"]

Python应用Dockerfile

FROM python:3.9-slim

WORKDIR /app

# 安装系统依赖
RUN apt-get update && apt-get install -y \
    gcc \
    && rm -rf /var/lib/apt/lists/*

# 复制requirements文件
COPY requirements.txt .

# 安装Python依赖
RUN pip install --no-cache-dir -r requirements.txt

# 复制应用代码
COPY . .

# 暴露端口
EXPOSE 8000

# 启动应用
CMD ["python", "app.py"]

多阶段构建

# 构建阶段
FROM node:16-alpine 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

# 复制nginx配置
COPY nginx.conf /etc/nginx/nginx.conf

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]

🔧 构建镜像

# 构建镜像
docker build -t 镜像名:标签 .

# 构建时指定Dockerfile
docker build -f Dockerfile.prod -t myapp:prod .

# 构建时传递参数
docker build --build-arg VERSION=1.0.0 -t myapp .

🐙 Docker Compose

Docker Compose用于定义和运行多容器Docker应用程序的工具。

📄 docker-compose.yaml基本结构

version: '3.8'  # 版本号

services:       # 服务定义
  服务名:
    build: ./目录           # 构建配置
    image: 镜像名:标签       # 使用镜像
    ports:                  # 端口映射
      - "主机端口:容器端口"
    volumes:                # 卷挂载
      - 主机路径:容器路径
    environment:            # 环境变量
      - 键=值
    depends_on:            # 依赖关系
      - 其他服务名
    networks:              # 网络配置
      - 网络名

volumes:        # 数据卷定义
  卷名:

networks:       # 网络定义
  网络名:
    driver: bridge

🎯 常用配置选项

服务配置详解

services:
  web:
    # 构建配置
    build:
      context: ./web          # 构建上下文
      dockerfile: Dockerfile  # Dockerfile路径
      args:                   # 构建参数
        VERSION: "1.0"
    
    # 镜像配置
    image: nginx:alpine
    container_name: my-web
    
    # 端口配置
    ports:
      - "8080:80"
      - "443:443"
    
    # 环境变量
    environment:
      - NODE_ENV=production
      - DB_HOST=db
      - REDIS_URL=redis://redis:6379
    
    # 环境变量文件
    env_file:
      - .env
      - .env.production
    
    # 卷挂载
    volumes:
      - ./html:/usr/share/nginx/html
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - static_volume:/var/www/static
    
    # 依赖关系
    depends_on:
      - db
      - redis
    
    # 网络配置
    networks:
      - frontend
      - backend
    
    # 重启策略
    restart: unless-stopped
    
    # 健康检查
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:80/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

🌐 实战示例

Web应用完整配置

version: '3.8'

services:
  # Web服务
  web:
    build: .
    container_name: myapp-web
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - DB_HOST=db
      - DB_PORT=5432
      - DB_NAME=myapp
      - DB_USER=postgres
      - REDIS_URL=redis://redis:6379
    depends_on:
      - db
      - redis
    networks:
      - app-network
    restart: unless-stopped

  # 数据库服务
  db:
    image: postgres:13
    container_name: myapp-db
    environment:
      - POSTGRES_DB=myapp
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=secretpassword
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql
    ports:
      - "5432:5432"
    networks:
      - app-network
    restart: unless-stopped

  # Redis服务
  redis:
    image: redis:6-alpine
    container_name: myapp-redis
    ports:
      - "6379:6379"
    volumes:
      - redis_data:/data
    networks:
      - app-network
    restart: unless-stopped
    command: redis-server --appendonly yes

  # Nginx反向代理
  nginx:
    image: nginx:alpine
    container_name: myapp-nginx
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./ssl:/etc/nginx/ssl:ro
    depends_on:
      - web
    networks:
      - app-network
    restart: unless-stopped

# 数据卷定义
volumes:
  postgres_data:
  redis_data:

# 网络定义
networks:
  app-network:
    driver: bridge

开发环境配置

version: '3.8'

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile.dev
    volumes:
      - .:/app
      - /app/node_modules  # 防止node_modules被覆盖
    ports:
      - "3000:3000"
      - "9229:9229"  # Node.js调试端口
    environment:
      - NODE_ENV=development
      - CHOKIDAR_USEPOLLING=true  # 支持热重载
    command: npm run dev
    depends_on:
      - db
      - redis
    networks:
      - dev-network

  db:
    image: mysql:8.0
    environment:
      - MYSQL_ROOT_PASSWORD=root
      - MYSQL_DATABASE=devdb
    ports:
      - "3306:3306"
    volumes:
      - mysql_dev_data:/var/lib/mysql
    networks:
      - dev-network

  redis:
    image: redis:6-alpine
    ports:
      - "6379:6379"
    networks:
      - dev-network

volumes:
  mysql_dev_data:

networks:
  dev-network:
    driver: bridge

⚡ 常用命令

# 启动所有服务(后台运行)
docker-compose up -d

# 启动指定服务
docker-compose up -d web

# 启动并查看日志
docker-compose up

# 停止所有服务
docker-compose down

# 停止并删除数据卷
docker-compose down -v

# 停止并删除镜像
docker-compose down --rmi all

# 重新构建并启动
docker-compose up -d --build

# 查看服务状态
docker-compose ps

# 查看日志
docker-compose logs
docker-compose logs -f web  # 实时查看web服务日志
docker-compose logs --tail=100  # 查看最后100行

# 进入容器
docker-compose exec web bash
docker-compose exec db mysql -u root -p

# 执行命令
docker-compose run web npm run test

# 扩展服务
docker-compose up -d --scale web=3

# 查看资源使用
docker-compose top

🔧 高级配置

环境变量文件

# .env文件
NODE_ENV=production
DB_HOST=db
DB_PORT=5432
DB_NAME=myapp
DB_USER=postgres
DB_PASSWORD=secretpassword

覆盖配置

# docker-compose.override.yml
version: '3.8'

services:
  web:
    volumes:
      - ./src:/app/src  # 开发时挂载源码
    environment:
      - NODE_ENV=development
    command: npm run dev

生产环境配置

# docker-compose.prod.yml
version: '3.8'

services:
  web:
    deploy:
      replicas: 3
      resources:
        limits:
          cpus: '0.5'
          memory: 512M
        reservations:
          cpus: '0.25'
          memory: 256M
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

🔒 Docker私有仓库

Docker私有仓库用于存储和管理自定义的Docker镜像。

🏗️ 搭建私有仓库

使用官方Registry镜像

# 拉取Registry镜像
docker pull registry

# 启动私有仓库
docker run -di --name=registry \
  -p 5000:5000 \
  -v /opt/registry:/var/lib/registry \
  registry

# 启动带认证的私有仓库
docker run -di --name=registry-auth \
  -p 5000:5000 \
  -v /opt/registry:/var/lib/registry \
  -v /opt/auth:/auth \
  -e REGISTRY_AUTH=htpasswd \
  -e REGISTRY_AUTH_HTPASSWD_REALM="Registry Realm" \
  -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
  registry

配置认证

# 安装htpasswd工具
apt install apache2-utils

# 创建认证文件
htpasswd -Bbn testuser testpass > /opt/auth/htpasswd

🔧 配置Docker客户端

# 修改Docker配置文件
vi /etc/docker/daemon.json

{
  "insecure-registries": ["私有仓库IP:5000"]
}

# 重启Docker
systemctl restart docker

📦 推送和拉取镜像

# 标记镜像
docker tag 本地镜像名:标签 私有仓库IP:5000/镜像名:标签

# 推送镜像
docker push 私有仓库IP:5000/镜像名:标签

# 拉取镜像
docker pull 私有仓库IP:5000/镜像名:标签

# 查看仓库中的镜像
curl http://私有仓库IP:5000/v2/_catalog

🔧 Docker Maven插件

Docker Maven插件用于在Maven构建过程中自动构建和推送Docker镜像。

📝 插件配置

pom.xml配置

<build>
    <plugins>
        <plugin>
            <groupId>com.spotify</groupId>
            <artifactId>dockerfile-maven-plugin</artifactId>
            <version>1.4.13</version>
            <configuration>
                <repository>your-registry/${project.artifactId}</repository>
                <tag>${project.version}</tag>
                <buildArgs>
                    <JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
                </buildArgs>
            </configuration>
        </plugin>
    </plugins>
</build>

Dockerfile示例

FROM openjdk:11-jre-slim

ARG JAR_FILE
COPY ${JAR_FILE} app.jar

EXPOSE 8080

ENTRYPOINT ["java", "-jar", "/app.jar"]

⚡ Maven命令

# 构建Docker镜像
mvn dockerfile:build

# 推送镜像到仓库
mvn dockerfile:push

# 构建并推送
mvn dockerfile:build dockerfile:push

# 指定标签
mvn dockerfile:build -Ddockerfile.tag=latest

# 强制重建
mvn dockerfile:build -Ddockerfile.noCache

🎯 高级配置

多环境配置

<profiles>
    <profile>
        <id>dev</id>
        <properties>
            <docker.registry>localhost:5000</docker.registry>
        </properties>
    </profile>
    <profile>
        <id>prod</id>
        <properties>
            <docker.registry>registry.example.com</docker.registry>
        </properties>
    </profile>
</profiles>

<build>
    <plugins>
        <plugin>
            <groupId>com.spotify</groupId>
            <artifactId>dockerfile-maven-plugin</artifactId>
            <configuration>
                <repository>${docker.registry}/${project.artifactId}</repository>
                <tag>${project.version}</tag>
            </configuration>
        </plugin>
    </plugins>
</build>