欢迎光临
我们一直在努力

硬核|Docker从入门到精通:镜像构建、仓库推送、Compose编排、生产部署全攻略

上周帮一个朋友排查线上问题,他一脸茫然地问我:“为什么我本地跑得好好的容器,到服务器上就起不来了?”我进服务器一看——镜像tag是latest,启动命令写的是npm start,连Dockerfile都没有打版本号。这是一个典型“会用但没真正理解Docker”的状态。

本文不讲虚的,从镜像拉取→容器运行→Dockerfile定制→镜像仓库推送→多容器编排Compose→生产环境部署,一条龙把Docker的所有基础但核心的操作讲透。全文每个命令都有场景说明和踩坑提示,让你从“会敲命令”变成“真懂容器”。

一、Docker核心概念(一句话建立认知模型)

  • 镜像(Image) :一个只读的模板,包含运行环境和代码,类比“类”。

  • 容器(Container) :镜像的运行实例,类比“对象”。

  • 仓库(Registry) :存放镜像的地方,Docker Hub是官方仓库。

  • Dockerfile:描述如何构建镜像的脚本。

  • docker-compose:定义和运行多容器的工具(YAML配置)。

理解这5个词,你已经掌握了50%的Docker思想。

二、镜像拉取与容器基础操作

2.1 拉取镜像(pull)

bash

# 从Docker Hub拉取nginx最新版
docker pull nginx

# 拉取指定版本
docker pull nginx:1.25

# 从私有仓库拉取(需先登录)
docker pull myregistry.com/myapp:1.0

踩坑提醒:不指定tag默认latest,但在生产环境中永远不要用latest——你不知道它指向哪个具体版本,下次拉取可能变了导致行为不一致。

2.2 查看本地镜像

bash

docker images
# 或
docker image ls

2.3 运行容器(run)

bash

# 最简单的运行(前台运行,Ctrl+C退出)
docker run nginx

# 后台运行 -d,映射端口 -p 主机端口:容器端口,命名 –name
docker run -d –name mynginx -p 8080:80 nginx

# 进入容器内部交互(常用调试)
docker exec -it mynginx /bin/bash

# 运行一次性命令(如查看环境变量)
docker exec mynginx env

常用run参数速查:

参数说明示例
-d 后台运行 -d
-p 端口映射 -p 8080:80
-v 挂载卷(持久化) -v /host/data:/app/data
-e 设置环境变量 -e MYSQL_ROOT_PASSWORD=123
–restart 重启策略 –restart=always
–network 指定网络 –network mynet

2.4 管理容器

bash

# 查看运行中容器
docker ps

# 查看所有容器(含已停止)
docker ps -a

# 停止/启动/重启
docker stop mynginx
docker start mynginx
docker restart mynginx

# 删除容器(需先停止)
docker rm mynginx

# 强制删除运行中容器
docker rm -f mynginx

# 查看容器日志
docker logs mynginx
docker logs -f mynginx # 实时跟踪

三、Dockerfile:定制自己的镜像

3.1 一个生产级Dockerfile示例(Node.js)

dockerfile

# 1. 指定基础镜像(尽量用alpine瘦身版)
FROM node:18-alpine AS builder

# 2. 设置工作目录
WORKDIR /app

# 3. 复制依赖文件(利用缓存层)
COPY package*.json ./
RUN npm ci –only=production && npm cache clean –force

# 4. 复制源代码
COPY . .

# 5. 多阶段构建:最终镜像只复制产物
FROM node:18-alpine
WORKDIR /app
COPY –from=builder /app/node_modules ./node_modules
COPY –from=builder /app/dist ./dist
COPY –from=builder /app/package.json ./

# 6. 声明运行时用户(非root安全)
RUN addgroup -g 1001 -S nodejs && \\
adduser -S nodejs -u 1001
USER nodejs

# 7. 暴露端口
EXPOSE 3000

# 8. 启动命令(建议用JSON数组形式)
CMD ["node", "dist/index.js"]

3.2 Dockerfile最佳实践

  • 利用构建缓存:把不常变的指令(如COPY package.json)放在前面,源代码放在后面。

  • 多阶段构建:最终镜像只包含运行必需文件,体积可减少80%以上。

  • 指定具体基础镜像tag:不要用node:latest,用node:18.17.0-alpine。

  • 最小权限原则:不要用root运行应用,创建普通用户。

  • 合并RUN命令:减少镜像层数,如RUN apt update && apt install -y curl && rm -rf /var/lib/apt/lists/*。

  • 3.3 构建镜像(build)

    bash

    # 基本构建
    docker build -t myapp:1.0 .

    # 指定Dockerfile路径
    docker build -t myapp:1.0 -f Dockerfile.prod .

    # 构建时不使用缓存
    docker build –no-cache -t myapp:1.0 .

    3.4 查看镜像层历史

    bash

    docker history myapp:1.0

    四、镜像仓库:推送与拉取

    4.1 登录仓库

    bash

    # Docker Hub
    docker login

    # 私有仓库(如阿里云/自建Harbor)
    docker login myregistry.com -u username -p password

    4.2 标记镜像(tag)

    bash

    # 语法:docker tag 源镜像 目标仓库地址/命名空间/镜像名:tag
    docker tag myapp:1.0 myregistry.com/dev/myapp:1.0

    4.3 推送镜像

    bash

    docker push myregistry.com/dev/myapp:1.0

    4.4 拉取私有镜像

    bash

    docker pull myregistry.com/dev/myapp:1.0

    4.5 仓库管理常用命令

    bash

    # 搜索镜像(Docker Hub)
    docker search nginx

    # 删除本地镜像
    docker rmi myapp:1.0

    # 清理未使用的镜像
    docker image prune -a

    五、数据持久化:Volume与Bind Mount

    5.1 两种挂载方式对比

    类型命令示例特点使用场景
    Volume(卷) -v myvolume:/data Docker管理,存于/var/lib/docker/volumes/ 数据库、配置文件持久化
    Bind Mount(绑定挂载) -v /host/path:/container/path 直接挂载宿主机目录 开发热加载、日志输出

    5.2 Volume操作

    bash

    # 创建卷
    docker volume create mydata

    # 查看卷列表
    docker volume ls

    # 挂载卷运行容器
    docker run -d -v mydata:/var/lib/mysql –name mysql mysql

    # 查看卷详情
    docker volume inspect mydata

    # 删除无用卷
    docker volume prune

    5.3 容器间共享卷

    bash

    # 创建一个共享卷
    docker volume create shared

    # 容器A挂载
    docker run -d –name app1 -v shared:/app/data busybox

    # 容器B挂载同一个卷
    docker run -d –name app2 -v shared:/app/data busybox

    六、docker-compose:多容器编排

    6.1 一个完整的docker-compose.yml示例(LNMP)

    yaml

    version: '3.8'

    services:
    nginx:
    image: nginx:1.25-alpine
    container_name: my-nginx
    ports:
    – "80:80"
    volumes:
    – ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
    – ./html:/usr/share/nginx/html
    depends_on:
    – php
    – mysql
    networks:
    – appnet

    php:
    build:
    context: ./php
    dockerfile: Dockerfile
    container_name: my-php
    volumes:
    – ./html:/var/www/html
    environment:
    – MYSQL_HOST=mysql
    – MYSQL_DB=mydb
    depends_on:
    – mysql
    networks:
    – appnet

    mysql:
    image: mysql:8.0
    container_name: my-mysql
    restart: always
    environment:
    MYSQL_ROOT_PASSWORD: root123
    MYSQL_DATABASE: mydb
    MYSQL_USER: app
    MYSQL_PASSWORD: app123
    volumes:
    – mysql-data:/var/lib/mysql
    ports:
    – "3306:3306"
    networks:
    – appnet

    volumes:
    mysql-data:

    networks:
    appnet:
    driver: bridge

    6.2 常用compose命令

    bash

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

    # 查看服务状态
    docker-compose ps

    # 查看日志
    docker-compose logs -f

    # 停止并删除容器、网络(默认不删volumes)
    docker-compose down

    # 停止并删除volumes
    docker-compose down -v

    # 重新构建镜像后启动
    docker-compose up -d –build

    # 扩容某个服务(比如php启动3个实例)
    docker-compose up -d –scale php=3

    # 执行一次性命令(如数据库迁移)
    docker-compose run php php artisan migrate

    6.3 Compose生产配置要点

  • 指定镜像tag:不要用latest,写具体版本。

  • 资源限制:避免容器耗尽主机资源。

  • yaml

    services:
    mysql:
    deploy:
    resources:
    limits:
    cpus: '2'
    memory: 2G
    reservations:
    memory: 1G

  • 健康检查:

  • yaml

    services:
    php:
    healthcheck:
    test: ["CMD", "curl", "-f", "http://localhost/health"]
    interval: 30s
    timeout: 10s
    retries: 3

  • 配置外部网络(让多个compose项目互通):

  • bash

    docker network create shared_network

    yaml

    networks:
    default:
    external:
    name: shared_network

    七、进阶编排:docker swarm vs kubernetes(简要)

    虽然Compose适合单机,但在生产环境往往需要集群编排。这里简要对比:

    特性Docker SwarmKubernetes
    复杂度 低,集成在Docker中 高,需独立部署
    服务发现 内置DNS 内置DNS+Service
    负载均衡 内置 多种Ingress
    滚动更新 支持 高级策略
    学习曲线 平缓 陡峭

    Swarm快速上手

    bash

    # 初始化集群
    docker swarm init –advertise-addr 192.168.1.10

    # 加入工作节点(在其他机器执行)
    docker swarm join –token <token> 192.168.1.10:2377

    # 部署stack(类似compose但支持集群)
    docker stack deploy -c docker-compose.yml myapp

    # 查看服务
    docker service ls

    # 扩容
    docker service scale myapp_php=5

    八、生产部署实战:一个完整的CI/CD视角

    8.1 流程概览

  • 开发者推送代码到Git

  • CI服务器拉取代码,执行测试

  • 构建Docker镜像,推送私有仓库

  • 部署服务器拉取新镜像,滚动更新容器

  • 8.2 镜像版本规范

    建议使用:<registry>/<project>:<git-commit-hash> 或 :build-<build-number>
    示例:myregistry.com/order-service:a1f9e3d

    8.3 部署脚本示例(bash)

    bash

    #!/bin/bash
    IMAGE_TAG=$(git rev-parse –short HEAD)
    REGISTRY="myregistry.com"
    PROJECT="order-api"

    # 构建
    docker build -t $REGISTRY/$PROJECT:$IMAGE_TAG .

    # 推送
    docker push $REGISTRY/$PROJECT:$IMAGE_TAG

    # 在生产服务器上拉取并更新(假设使用docker-compose)
    ssh user@prod-server "
    docker pull $REGISTRY/$PROJECT:$IMAGE_TAG
    cd /app/$PROJECT
    sed -i 's|image:.*|image: $REGISTRY/$PROJECT:$IMAGE_TAG|' docker-compose.yml
    docker-compose up -d –no-deps –scale $PROJECT=3 $PROJECT
    "

    8.4 镜像清理策略

    bash

    # 定期删除旧镜像(保留最近5个)
    docker image prune -a –filter "until=168h" -f

    九、常见问题与排障

    9.1 容器无法启动

    bash

    # 查看日志
    docker logs <container>

    # 检查退出码
    docker ps -a

    # 进入停止状态的容器(需要先启动一个调试容器)
    docker run -it –entrypoint /bin/sh myapp:1.0

    9.2 端口冲突

    bash

    # 查看宿主机端口占用
    netstat -tulnp | grep :8080

    # 或者改docker映射端口
    docker run -p 8081:80 …

    9.3 磁盘占满

    bash

    # 查看docker占用空间
    docker system df

    # 清理未使用资源
    docker system prune -a –volumes

    9.4 容器内时区不对

    yaml

    # compose中挂载时区文件
    volumes:
    – /etc/localtime:/etc/localtime:ro
    – /etc/timezone:/etc/timezone:ro

    或Dockerfile中设置环境变量:

    dockerfile

    ENV TZ=Asia/Shanghai
    RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

    十、总结:Docker命令脑图与学习路线

    text

    docker
    ├── 镜像管理
    │ ├── pull / push
    │ ├── build (Dockerfile)
    │ ├── tag / rmi
    │ └── history / inspect
    ├── 容器生命周期
    │ ├── run ( -d -p -v -e –name –restart )
    │ ├── start / stop / restart
    │ ├── rm ( -f )
    │ └── exec / logs
    ├── 存储
    │ ├── volume (create / ls / inspect / prune)
    │ └── bind mount
    ├── 网络
    │ ├── network create / ls / inspect
    │ └── bridge / overlay / host
    ├── 编排
    │ ├── docker-compose (up / down / logs / exec)
    │ └── docker stack (swarm)
    └── 系统
    ├── system df / prune
    └── info / version

    学习建议:

  • 先敲熟 run、exec、logs、ps 这四个最常用命令。

  • 自己写一个简单的 Dockerfile(比如一个 Python Flask 应用),构建并运行。

  • 学会用 Compose 启动 LNMP/MEAN 完整环境。

  • 最后再接触 Swarm/K8s。

  • 掌握 Docker 并不难,难的是形成“任何应用都应该容器化”的思维习惯。当你看到一个新项目,脑子里自动浮现出 Dockerfile 和 compose 的结构时,你就真正入门了。

    赞(0)
    未经允许不得转载:171主机测评 » 硬核|Docker从入门到精通:镜像构建、仓库推送、Compose编排、生产部署全攻略
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址