Docker 快速入门:从零到实践的全方位学习笔记

13 35~45 分钟

篇章一:Docker 核心概念入门

在深入实践之前,我们首先需要理解 Docker 的几个基本概念,这就像学习一门新语言前先掌握它的字母表一样重要。

1. 什么是 Docker?

简单来说,Docker 是一种容器化技术,它能将你的应用程序及其所有依赖打包到一个独立的、标准化的运行环境——容器(Container)中。运行这些容器的计算机我们称之为宿主机(Host)

2. Docker vs. 虚拟机 (VM)

你可能会问,这听起来和虚拟机很像,它们有什么区别?

  • 虚拟机:每个虚拟机都包含一个完整的操作系统内核。这使得它们相对笨重,启动慢,资源消耗大。
  • Docker 容器:所有容器共享宿主机的操作系统内核。这使得容器非常轻量级,启动速度极快(秒级甚至毫秒级),资源占用也更少。

3. 镜像 (Image)

镜像是创建容器的模板。你可以把它想象成软件的“安装包”或者制作糕点的“模具”。我们用一个镜像(模具)可以创建出多个一模一样的容器(糕点)。

4. 仓库 (Registry)

仓库是集中存放和分发镜像的地方。这就像是 GitHub 存储代码仓库一样。

  • Docker Hub 是 Docker 官方的公共仓库,上面有海量由官方或社区贡献的镜像,任何人都可以上传或下载。

理解了容器、镜像、仓库这三大核心概念,你就已经敲开了 Docker 的大门!

篇章二:Docker 环境安装

万事俱备,只欠东风。接下来,我们将在不同操作系统上安装 Docker。Docker 本质上是基于 Linux 内核的技术,因此在 Windows 和 macOS 上,它会通过一个轻量级的 Linux 子系统来运行。

1. 在 Linux (Ubuntu) 上安装

在 Linux 上安装 Docker 是最原生、最推荐的方式。

  1. 打开终端,执行以下命令下载安装脚本:

    curl -fsSL https://get.docker.com -o get-docker.sh
    
  2. 使用管理员权限执行安装脚本:

    sudo sh get-docker.sh
    

    提示sudo (Superuser Do) 用于获取管理员权限。如果你的当前用户不是 root,在后续执行所有 docker 命令时,都需要在前面加上 sudo

等待片刻,安装即可完成。

2. 在 Windows 上安装

  1. 开启所需功能

    • 在任务栏搜索 "启用或关闭 Windows 功能"。
    • 勾选 "虚拟机平台 (Virtual Machine Platform)" 和 "适用于 Linux 的 Windows 子系统 (Windows Subsystem for Linux, WSL)"。
    • 根据提示重启电脑。
  2. 安装并配置 WSL

    • 电脑重启后,以管理员身份打开命令提示符 (CMD)。

    • 设置 WSL 默认版本为 2:

      wsl --set-default-version 2
      
    • 更新 WSL 内核:

      wsl --update
      # 国内网络建议使用以下命令,加速下载
      wsl --update --web-download
      
  3. 安装 Docker Desktop

    • Docker 官网下载适用于 Windows 的 Docker Desktop 安装包。
    • 双击安装,一路 "Next" 即可。安装完成后,确保 Docker Desktop 处于运行状态。
  4. 验证安装

    • 打开一个新的终端(CMD 或 PowerShell),输入:

      docker --version
      
    • 如果成功打印出版本号,说明安装成功。

3. 在 macOS 上安装

在 Mac 上安装最为简单。根据你的芯片(Intel 或 Apple Silicon M系列)从 Docker 官网下载对应的 .dmg 安装包,拖拽安装即可。

篇章三:Docker 镜像管理

环境就绪,我们来学习如何管理 Docker 的“模具”——镜像。

1. 拉取镜像 (docker pull)

docker pull 命令用于从仓库下载镜像。一个完整的镜像名结构如下: [registry_address]/[namespace]/[repository_name]:[tag]

  • registry_address: 仓库地址,如 docker.io (Docker Hub)。官方仓库地址可以省略。
  • namespace: 命名空间,通常是作者或组织名。官方镜像的 library 命名空间可以省略。
  • repository_name: 镜像库名称,如 nginx
  • tag: 标签,通常是版本号,如 1.28.0latest 或不写表示最新版。

示例

# 完整写法
sudo docker pull docker.io/library/nginx:latest

# 简化写法(最常用)
sudo docker pull nginx

国内网络加速: 如果 docker pull 因网络问题失败,可以配置国内镜像加速器。

  • Linux: 修改 /etc/docker/daemon.json 文件,添加以下内容后重启 Docker 服务。

    {
      "registry-mirrors": ["https://hub-mirror.c.163.com", "https://mirror.baidubce.com"]
    }
    

    重启命令: sudo systemctl restart docker

  • Windows/Mac: 打开 Docker Desktop -> Settings -> Docker Engine,在 JSON 配置中加入 "registry-mirrors": [...] 字段,然后点击 "Apply & Restart"。

2. 查看本地镜像 (docker images)

此命令可以列出所有已经下载到本地的镜像。

sudo docker images

3. 删除本地镜像 (docker rmi)

rmi 是 Remove Image 的缩写。你可以通过镜像名或镜像ID来删除。

# 通过镜像名删除
sudo docker rmi nginx

# 通过镜像ID删除(ID可以只写前几位,能唯一区分即可)
sudo docker rmi 3f8a00f42922

4. 指定 CPU 架构 (--platform)

在某些场景下,如在 ARM 架构的设备(如树莓派、香橙派)上运行时,需要拉取特定 CPU 架构的镜像。

# 拉取 ARM64 架构的镜像
docker pull --platform=linux/arm64 some-image

注意:Mac M系列芯片也是 ARM64 架构,但 Docker Desktop 会通过 QEMU 模拟来兼容部分 AMD64 镜像,不过可能会有性能损耗或兼容性问题。

篇章四:Docker 容器操作(核心)

这是本篇笔记最重要的部分,我们将学习如何使用镜像创建和管理容器。

1. 创建并运行容器 (docker run)

这是最核心的命令,它从一个镜像创建一个新的容器并启动它。

# 启动一个 nginx 容器
sudo docker run nginx

这会在前台启动容器,并会持续输出日志,阻塞当前终端。

docker run 的常用参数:

  • -d (Detached): 后台运行容器,并返回容器ID。这是最常用的模式。

    sudo docker run -d nginx
    
  • -p (Port Mapping): 端口映射,格式为 -p <宿主机端口>:<容器端口>。 Docker 容器网络默认与宿主机隔离,需要通过端口映射才能从外部访问容器内的服务。

    # 将宿主机的8080端口映射到容器的80端口
    sudo docker run -d -p 8080:80 nginx
    

    现在,访问 http://<宿主机IP>:8080 就能看到 Nginx 的欢迎页面了。

  • -v (Volume): 挂载卷,用于数据持久化,格式为 -v <宿主机目录/卷名>:<容器内目录>。 容器被删除时,其内部数据也会丢失。挂载卷可以将容器内的数据同步到宿主机,实现持久化。

    • 绑定挂载 (Bind Mount): 直接指定宿主机路径。

      # 将宿主机的 /home/user/html 目录挂载到容器的 /usr/share/nginx/html
      sudo docker run -d -p 8080:80 -v /home/user/html:/usr/share/nginx/html nginx
      

      注意:绑定挂载时,宿主机目录会覆盖容器内目录。如果宿主机目录为空,容器内对应目录也会变空。

    • 命名卷挂载 (Named Volume): 由 Docker 管理的存储空间。

      # 1. 创建一个命名卷
      sudo docker volume create my-nginx-data
      
      # 2. 运行时使用卷名挂载
      sudo docker run -d -p 8080:80 -v my-nginx-data:/usr/share/nginx/html nginx
      

      优点:命名卷首次挂载时,会将容器内目录的原始文件复制到卷中,避免了空目录覆盖的问题。

  • -e (Environment): 设置环境变量。

    # 启动一个 MongoDB,并通过环境变量设置用户名和密码
    sudo docker run -d -p 27017:27017 \
      -e MONGO_INITDB_ROOT_USERNAME=myuser \
      -e MONGO_INITDB_ROOT_PASSWORD=mypassword \
      mongo
    
  • --name: 给容器指定一个自定义的名字,方便管理。

    sudo docker run -d --name my-web-server -p 8080:80 nginx
    
  • --restart: 配置重启策略。

    • --restart=always: 无论因何种原因停止,容器都会自动重启。
    • --restart=unless-stopped: 除非是手动执行 docker stop 停止,否则都会自动重启(推荐用于生产环境)。
  • -it--rm: 常用组合,用于临时调试。

    • -it: 提供一个交互式的 TTY 终端。
    • --rm: 容器退出后自动删除。
    # 启动一个临时的、轻量级的 Alpine Linux 容器进行调试
    sudo docker run -it --rm alpine sh
    # (进入容器内)
    # exit (退出后容器自动销毁)
    

2. 容器生命周期管理

  • docker ps: 查看正在运行的容器 (ps: Process Status)。
    • docker ps -a: 查看所有容器(包括已停止的)。
  • docker stop <容器名/ID>: 停止一个正在运行的容器。
  • docker start <容器名/ID>: 启动一个已停止的容器。
  • docker rm <容器名/ID>: 删除一个已停止的容器。
    • docker rm -f <容器名/ID>: 强制删除一个正在运行的容器。
  • docker logs <容器名/ID>: 查看容器日志。
    • docker logs -f <容器名/ID>: 实时滚动查看日志。

3. 进入容器内部 (docker exec)

exec 命令可以在一个正在运行的容器内部执行命令。最常见的用法是进入容器的 shell 环境进行调试。

# 1. 先启动一个 nginx 容器
sudo docker run -d --name my-nginx nginx

# 2. 进入该容器的 shell 环境
sudo docker exec -it my-nginx /bin/sh
  • -it: 保持交互式连接。
  • /bin/sh/bin/bash: 容器内可用的 shell 程序。

进入容器后,你就可以像在普通 Linux 系统里一样执行命令,查看文件,调试程序了。

篇章五:自定义镜像 (Dockerfile)

当官方镜像无法满足你的需求时,就需要自己构建镜像。Dockerfile 就是一个用来定义镜像构建步骤的文本文件。

类比:如果镜像是“模具”,那 Dockerfile 就是“模具的设计图纸”。

Dockerfile 实战:打包一个 Python Web 应用

假设我们有一个简单的 FastAPI 应用:

  • main.py:

    from fastapi import FastAPI
    app = FastAPI()
    @app.get("/")
    def read_root():
        return {"Hello": "World"}
    
  • requirements.txt:

    fastapi
    uvicorn
    

1. 编写 Dockerfile (文件名固定,D大写,无后缀)

# 1. 选择一个包含 Python 环境的基础镜像
FROM python:3.11-slim

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

# 3. 将当前目录下的所有文件复制到镜像的 /app 目录
COPY . .

# 4. 在镜像内执行命令,安装依赖
RUN pip install --no-cache-dir -r requirements.txt

# 5. 声明容器对外暴露的端口(仅为文档作用,无实际效果)
EXPOSE 8000

# 6. 定义容器启动时默认执行的命令
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

2. 构建镜像 (docker build)Dockerfile 所在目录下执行:

# -t 表示 tag,给镜像命名
# . 表示使用当前目录作为构建上下文
sudo docker build -t my-python-app:1.0 .

3. 运行自定义镜像

sudo docker run -d --name my-app-instance -p 8000:8000 my-python-app:1.0

现在访问 http://<宿主机IP>:8000 就可以看到 {"Hello": "World"} 了。

4. 推送镜像到 Docker Hub (docker push)

  1. 登录 Docker Hub:

    sudo docker login
    
  2. 给镜像打上符合规范的标签: <你的DockerHub用户名>/<镜像名>:<版本号>

    sudo docker tag my-python-app:1.0 your-username/my-python-app:1.0
    
  3. 推送镜像:

    sudo docker push your-username/my-python-app:1.0
    

现在,任何人都可以通过 docker pull your-username/my-python-app:1.0 下载你的镜像了!

篇章六:Docker 网络

Docker 提供了多种网络模式来满足不同场景的需求。

  1. Bridge (桥接模式): 默认模式。Docker 会创建一个虚拟网桥,所有容器连接到这个网桥上,并分配一个内部 IP。容器间可以通过内部 IP 通信,但与宿主机隔离。

  2. 自定义 Bridge 网络: 这是推荐的做法。我们可以创建一个自定义网络,让相关的容器加入其中。

    # 1. 创建网络
    sudo docker network create my-app-net
    
    # 2. 启动容器并加入网络
    sudo docker run -d --name db --network my-app-net mongo
    sudo docker run -d --name web --network my-app-net -p 80:80 my-webapp
    

    好处:在同一个自定义网络中,容器之间可以直接通过容器名(如 db)作为主机名进行通信,Docker 内置了 DNS 解析。

  3. Host (主机模式): 容器直接共享宿主机的网络栈,不再有网络隔离。容器的服务直接暴露在宿主机的端口上,无需 -p 映射。性能最好,但牺牲了安全性。

    sudo docker run -d --network host nginx
    
  4. None (无网络模式): 容器拥有自己的网络栈,但不进行任何网络配置。一个完全隔离的网络环境。

篇章七:容器编排 (Docker Compose)

当你的应用由多个容器(如前端、后端、数据库、缓存)组成时,手动管理 docker run 命令会变得非常繁琐。Docker Compose 正是为此而生。它是一个用于定义和运行多容器 Docker 应用程序的工具。

你只需使用一个 YAML 文件来配置应用的服务,然后用一条命令,就可以创建并启动所有服务。

Docker Compose 实战:部署 MongoDB 和 Mongo Express

1. 创建 docker-compose.yml 文件 这个文件清晰地定义了两个服务:一个数据库 (db) 和一个数据库管理界面 (mongo-express)。

version: '3.8'

services:
  db:
    image: mongo:latest
    container_name: my-mongo-db
    restart: unless-stopped
    volumes:
      - mongo-data:/data/db

  mongo-express:
    image: mongo-express:latest
    container_name: my-mongo-express
    restart: unless-stopped
    ports:
      - "8081:8081"
    environment:
      - ME_CONFIG_MONGODB_SERVER=db  # 使用服务名 'db' 连接数据库
      - ME_CONFIG_MONGODB_ADMINUSERNAME=myuser
      - ME_CONFIG_MONGODB_ADMINPASSWORD=mypassword
    depends_on:
      - db  # 确保 db 服务先于此服务启动

volumes:
  mongo-data:

亮点

  • services 下的 dbmongo-express 分别对应一个容器。
  • image, ports, volumes, environment 等参数与 docker run 的标志一一对应。
  • Docker Compose 会自动创建一个默认网络,并将所有服务加入其中,所以 mongo-express 可以直接通过服务名 db 访问数据库。
  • depends_on 定义了服务间的启动依赖。

2. 使用 Docker Compose 命令docker-compose.yml 文件所在目录下执行:

  • 启动所有服务 (后台模式):

    docker compose up -d
    
  • 停止并删除所有服务、网络和卷:

    docker compose down
    
  • 仅停止服务 (不删除):

    docker compose stop
    
  • 启动已停止的服务:

    docker compose start
    

Docker Compose 极大地简化了多容器应用的部署和管理,是开发和测试环境的利器。对于更大规模、更复杂的生产环境集群,你可能需要了解更强大的编排工具,如 Kubernetes (K8s)

总结

恭喜你!通过这篇笔记,你已经系统地学习了 Docker 的核心知识体系:

  • 三大概念:镜像、容器、仓库。
  • 环境搭建:在主流操作系统上安装 Docker。
  • 镜像管理pull, images, rmi
  • 容器全生命周期管理run, ps, stop, start, rm, logs, exec
  • 自定义镜像:通过 Dockerfilebuild 命令创建自己的镜像。
  • 网络模型:理解 Bridge 和 Host 模式,并学会使用自定义网络。
  • 容器编排:使用 Docker Compose 优雅地管理多容器应用。


上一篇 力扣-统计数组中的元素
下一篇 从零开始:在自有服务器上搭建一套完整的Git代码部署工作流