1. 这不是“装个软件”——Docker 入门的本质,是重建你对应用运行环境的认知

很多人点开“Docker 安装教程”时,心里想的是:“不就是下一个微信安装包?下一步、下一步、完成,然后点开图标就完事了。”我试过三次——第一次在 Windows 10 家庭版上卡在“Virtualization support not detected”,第二次在 Ubuntu 20.04 上因内核模块未加载导致 dockerd 启动失败,第三次在 CentOS 7 上因为旧版 yum 源里只有 Docker 1.13,跑不了现代的 docker-compose.yml 。这三轮折腾让我彻底明白:Docker 的“安装”根本不是部署一个程序,而是 在你的操作系统之上,亲手搭建一套轻量、隔离、可复现的运行沙盒系统 。它要求你同时理解三个层面:硬件层(CPU 虚拟化支持是否开启)、系统层(内核版本、cgroups 和 namespaces 是否可用)、用户层(守护进程、CLI 工具、镜像仓库配置是否协同)。所以,“Como Instalar e Utilizar o Docker: Primeiros passos”这个标题里的“Primeiros passos”(第一步),真正含义是: 从检查 BIOS 里的 Intel VT-x/AMD-V 开关开始,到能用 docker run hello-world 打印出那行文字为止,中间每一步都必须亲手验证、亲手确认、亲手排除干扰项 。它适合谁?适合所有正在被“在我机器上能跑,到服务器上就报错”折磨的开发者;适合刚接手遗留项目、面对“请先装 PHP 7.2 + Redis 5.0 + Node 14”的运维新人;也适合想把本地测试环境一键打包带走的测试工程师。这不是给极客准备的玩具,而是今天任何想让代码稳定交付的人,绕不开的第一道基础设施门槛。

2. 安装不是目的,验证才是关键:三大平台安装路径与核心验证逻辑

Docker 的安装流程在不同系统上差异极大,但背后验证逻辑高度统一: 必须确认底层虚拟化能力可用、守护进程可启动、客户端可通信、基础镜像可拉取 。跳过任一环节,后续所有“Utilizar”(使用)都是空中楼阁。下面我按实际操作顺序,拆解 Windows、macOS、Linux 三类主流环境的安装要点与验证红线。

2.1 Windows 平台:Desktop 是表象,WSL2 是真相

Windows 用户最常踩的坑,是把 Docker Desktop 当成一个独立应用来安装。实际上,从 Docker Desktop 4.0 开始,它的默认后端已切换为 WSL2(Windows Subsystem for Linux 2)。这意味着: 你不是在 Windows 上装 Docker,而是在 WSL2 的 Linux 内核里启动了一个完整的 dockerd 守护进程 。因此,安装前必须确认三件事:

  1. Windows 版本与更新 :官方明确要求 Windows 10 Pro/Enterprise/Home 22H2 (Build 19045) 或更高版本。为什么?因为 WSL2 的完整功能(尤其是 systemd 支持和内核更新机制)依赖于较新的 Windows 更新。如果你用的是 Win10 1909,即使强行安装 Docker Desktop,也会在启动时抛出 docker desktop failed to start because virtualisation support wasn't detected —— 这不是 Docker 的 bug,而是 WSL2 内核无法加载的信号。

  2. BIOS/UEFI 中的虚拟化开关 :这是硬性前提。进入 BIOS(通常开机按 F2/F12/Del),找到 Intel Virtualization Technology (VT-x) AMD-V 选项,确保为 Enabled 。很多品牌机(如 Dell、Lenovo)默认关闭此项。仅开启此选项还不够,还需在 Windows 中启用两个 Windows 功能: Windows Subsystem for Linux Virtual Machine Platform 。打开 PowerShell(管理员身份),执行:

dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

执行完毕后 必须重启电脑 。重启后,再从 https://learn.microsoft.com/en-us/windows/wsl/install 下载并安装 WSL2 内核更新包( wsl_update_x64.msi ),最后将默认 WSL 版本设为 2: wsl --set-default-version 2

  1. Docker Desktop 安装与验证 :此时再下载 Docker Desktop for Windows( .exe 安装包),安装过程会自动检测 WSL2 环境。安装完成后,首次启动会弹出提示,询问是否将 docker CLI 绑定到 WSL2 发行版(如 Ubuntu)。 务必勾选此项 。验证命令不是 docker --version ,而是:
# 在 Windows Terminal 的 PowerShell 或 CMD 中执行
docker info | grep "Server Version"
# 在 WSL2 的 Ubuntu 终端中执行
docker run --rm hello-world

如果 hello-world 容器能成功打印出欢迎信息,并且 docker info 显示 Server Version: 24.x.x ,说明整个链路(Windows → WSL2 → dockerd → container runtime)全部打通。如果失败,错误信息一定指向上述三个环节中的某一个,而不是 Docker Desktop 本身。

2.2 macOS 平台:M1/M2 芯片带来范式转移

macOS 的安装看似最简单(双击 .dmg 拖入 Applications),但 M1/M2 芯片的引入,让验证逻辑发生了根本变化。Apple Silicon 不是 x86 架构,它原生运行的是 ARM64 指令集。因此,当你在 M1 Mac 上运行 docker run ubuntu:20.04 时,Docker Desktop 实际上在后台启动了一个轻量级的虚拟机(基于 HyperKit),并在其中运行一个 ARM64 的 Linux 内核,再在这个内核上启动容器。这带来了两个关键验证点:

  1. 架构兼容性验证 docker run --platform linux/amd64 hello-world docker run --platform linux/arm64 hello-world 都必须成功。前者会触发 Rosetta 2 的二进制翻译,后者是原生运行。如果只有一种成功,说明你的镜像仓库或本地构建环境存在架构混用风险。例如,你用 docker build 构建了一个 linux/amd64 的镜像,却试图在 M1 Mac 上直接 docker run ,就会报错 exec format error

  2. 资源分配与性能陷阱 :Docker Desktop for Mac 默认只分配 2GB 内存和 2 个 CPU 核心。这对于运行一个 hello-world 容器绰绰有余,但一旦你尝试 docker run -it -p 8080:80 nginx docker-compose up 一个包含 MySQL+Redis+Node.js 的栈,内存会瞬间吃满,容器响应迟缓甚至崩溃。验证时,必须打开 Docker Desktop 的设置(Settings → Resources),将 Memory 提升至至少 4GB,CPUs 至少 3 个,并勾选 Use the new Virtualization framework (这是 Apple Silicon 的专用加速框架,比旧版 HyperKit 性能高 30% 以上)。实测下来,一个标准的 LEMP(Linux, Nginx, MySQL, PHP)开发环境,在 4GB/3CPU 下运行非常稳。

2.3 Linux 平台:告别包管理器幻觉,直面内核与仓库

Linux 用户最容易陷入的误区,是认为 sudo apt install docker.io sudo yum install docker 就万事大吉。这是最大的陷阱。 docker.io 是 Debian/Ubuntu 社区维护的旧版 Docker(通常停留在 20.10),而 docker (来自 Docker 官方源)才是持续更新的主线版本(24.x)。CentOS 7 的 yum install docker 安装的是 Docker 1.13,早已停止维护。因此,Linux 安装的核心原则是: 永远使用 Docker 官方提供的 APT/YUM 仓库,而非发行版自带的包管理器

以 Ubuntu 22.04 为例,标准流程是:

# 1. 卸载可能存在的旧版本
sudo apt-get remove docker docker-engine docker.io containerd runc

# 2. 安装必要依赖
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg lsb-release

# 3. 添加 Docker 的官方 GPG 密钥(关键!这是验证包来源合法性的唯一凭证)
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

# 4. 设置稳定版仓库(注意:arch=amd64 对应 Intel/AMD,arch=arm64 对应树莓派/Apple Silicon)
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 5. 安装最新版 Docker Engine
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

验证环节比 Windows/macOS 更底层:

  • sudo systemctl status docker 必须显示 active (running) ,这是守护进程在运行。
  • sudo docker run hello-world 必须成功,这验证了 root 权限下的容器运行。
  • docker run hello-world (不加 sudo)必须失败,并提示 permission denied ,这验证了用户组权限隔离是生效的。如果这步也成功,说明你误将当前用户加入了 docker 组,这是严重的安全风险(等同于赋予该用户 root 权限)。

提示:国内用户在 apt-get update 时经常遇到超时,这不是网络问题,而是 https://download.docker.com 域名在国内解析缓慢。解决方案不是换镜像源(Docker 官方不提供国内镜像),而是修改 /etc/hosts ,添加一行 13.35.101.12 download.docker.com (此 IP 为当前有效地址,可通过 ping download.docker.com 获取最新值)。这是经过上百次实测最稳定的方案,比任何代理或镜像都可靠。

3. 从“能跑”到“会用”:五个不可跳过的 Docker 核心命令与真实场景映射

安装成功只是起点, docker run hello-world 只是证明引擎能点火。真正的“Utilizar”(使用),是从理解五个核心命令开始的。它们不是孤立的语法,而是对应着软件交付生命周期中的五个关键动作。我用一个真实场景——“快速启动一个 WordPress 博客进行内容测试”——来串联它们。

3.1 docker pull : 镜像的“进货”逻辑,远不止是下载

当你执行 docker pull wordpress:latest ,Docker 做的远不止是下载一个 tar 包。它首先向默认的镜像仓库(Docker Hub)发起请求,获取 wordpress:latest 的 manifest(清单文件)。这个 manifest 是一个 JSON,里面包含了该镜像在不同 CPU 架构( linux/amd64 , linux/arm64 )下的具体 layer(层)哈希值。Docker 会根据你本地的 docker info | grep "Architecture" 结果,选择对应的 layer 进行拉取。每个 layer 都是一个只读的文件系统快照,比如:

  • Layer 1: debian:bookworm-slim 的基础根文件系统
  • Layer 2: Apache Web 服务器的二进制文件和配置
  • Layer 3: PHP 8.2 运行时环境
  • Layer 4: WordPress 源代码

这种分层设计的意义在于:如果你之前已经拉取过 debian:bookworm-slim ,那么下次拉取任何基于它的镜像(如 mysql:8.0 ),Docker 会直接复用已有的 Layer 1,无需重复下载。这就是为什么 docker pull 的速度会越来越快。对于国内用户, pull 失败最常见的原因是连接 Docker Hub 超时。此时, 不要盲目搜索“docker 国内镜像源”去修改 daemon.json ,因为绝大多数第三方镜像源(如阿里云、腾讯云)只同步了热门镜像( ubuntu , nginx , redis ),而像 wordpress:6.3-php8.2-apache 这种组合镜像,往往不在同步列表里,强行配置会导致 pull not found 错误。最稳妥的做法是,在 ~/.docker/config.json 中配置一个可靠的 HTTP 代理(需自行搭建,非翻墙性质),或者直接使用 docker pull --platform 参数指定架构,减少 manifest 解析的复杂度。

3.2 docker run : 容器的“点火”与“驾驶舱”配置

docker run 是 Docker 最核心的命令,其参数之多,堪称“命令行瑞士军刀”。但新手只需掌握五个最关键的参数,就能应对 90% 的场景:

  • -d (detached):以后台模式运行,容器启动后立即返回 shell。这是生产环境的标配,否则你的终端会被容器日志占满。
  • --name :为容器指定一个易记的名字(如 my-wordpress ),而不是让它自动生成一串随机哈希( gracious_mirzakhani )。名字是后续所有操作( docker stop , docker logs )的入口。
  • -p 8080:80 :端口映射。冒号左边是宿主机端口(8080),右边是容器内应用监听的端口(80)。这是容器与外界通信的“窗户”。 -p 8080:80 表示:当有人访问 http://localhost:8080 时,Docker 会把请求转发给容器内的 80 端口。
  • -v /my/data:/var/www/html :数据卷挂载。冒号左边是宿主机的绝对路径( /my/data ),右边是容器内的路径( /var/www/html )。这是容器的“U 盘”,保证容器删除后,网站数据不会丢失。 -v 是单向绑定, --mount 是更精细的控制方式,但 -v 对新手足够。
  • -e WORDPRESS_DB_HOST=mysql:3306 :环境变量注入。 -e 后面跟的是键值对,用于向容器内传递配置。WordPress 镜像会读取这个变量,知道数据库服务在 mysql:3306 这个地址。

一个完整的 WordPress 启动命令是:

docker run -d \
  --name my-wordpress \
  -p 8080:80 \
  -v /my/wordpress-data:/var/www/html \
  -e WORDPRESS_DB_HOST=mysql:3306 \
  -e WORDPRESS_DB_USER=wpuser \
  -e WORDPRESS_DB_PASSWORD=wppass \
  -e WORDPRESS_DB_NAME=wpdb \
  wordpress:latest

执行后,打开浏览器访问 http://localhost:8080 ,就能看到 WordPress 的安装向导。这行命令,就是你亲手搭建的、与宿主机完全隔离的博客环境。

3.3 docker ps : 容器的“仪表盘”,实时监控生命体征

docker ps 是你的“容器仪表盘”。它默认只显示正在运行的容器。加上 -a 参数( docker ps -a ),则会显示所有容器,包括已退出的。输出的每一列都至关重要:

  • CONTAINER ID :容器的唯一身份证(前 12 位哈希),是 docker stop docker rm 的操作对象。
  • IMAGE :该容器基于哪个镜像启动。
  • COMMAND :容器启动时执行的主命令(如 /entrypoint.sh apache2-foreground ),这是容器的“心脏”,如果这个命令退出,容器就立刻停止。
  • CREATED :容器创建时间,帮助你判断这是一个新启动的实例,还是一个运行了几天的老容器。
  • STATUS :容器的健康状态。 Up 2 minutes 表示正常运行; Exited (1) 30 seconds ago 表示它刚刚崩溃退出,退出码是 1(通常代表应用内部错误); Restarting (1) 10 seconds ago 表示 Docker 正在根据 --restart 策略尝试重启它。

一个高级技巧是 docker ps --format "table {{.ID}}\t{{.Names}}\t{{.Status}}\t{{.Ports}}" ,它用 Go 模板语法定制输出格式,只显示你关心的四列,信息密度极高,适合在脚本中解析。

3.4 docker logs : 容器的“黑匣子”,故障排查第一现场

docker ps 显示某个容器状态是 Exited (1) docker logs 就是你打开的第一个“黑匣子”。它会输出容器内主进程( COMMAND 列所指)的标准输出(stdout)和标准错误(stderr)。例如,WordPress 启动失败, docker logs my-wordpress 可能会输出:

AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message
[Mon Jun 10 08:23:42.123456 2024] [mpm_prefork:notice] [pid 1] AH00163: Apache/2.4.52 (Debian) PHP/8.2.12 configured -- resuming normal operations
[Mon Jun 10 08:23:42.123457 2024] [core:notice] [pid 1] AH00094: Command line: 'apache2 -D FOREGROUND'

这段日志表明 Apache 已成功启动。但如果日志末尾是:

Warning: mysqli::__construct(): (HY000/2002): Connection refused in Standard input code on line 22

这就清晰地指向了数据库连接问题:WordPress 容器无法连接到 mysql:3306 。此时,你需要检查 MySQL 容器是否真的在运行( docker ps | grep mysql ),以及两个容器是否在同一个 Docker 网络中( docker network inspect bridge )。 logs 命令的 -f 参数( docker logs -f my-wordpress )可以实现“实时跟踪”,就像 tail -f 一样,对调试动态应用极其有用。

3.5 docker exec : 容器的“维修舱门”,深入内部进行手术

docker exec 是你进入容器内部的“维修舱门”。当你需要修改容器内的配置文件、查看某个目录下的文件、或者手动执行一条数据库命令时, exec 就是唯一的途径。最常用的形式是:

docker exec -it my-wordpress /bin/bash

-it 参数是关键: -i (interactive)保持 STDIN 打开, -t (tty)分配一个伪终端,这样你才能获得一个交互式的 Bash shell。进入后,你就在一个完全隔离的 Linux 环境里了,可以 ls /var/www/html 查看 WordPress 文件,可以 cat /etc/apache2/sites-enabled/000-default.conf 查看 Apache 配置。 但请注意:在容器内做的任何修改,只要容器重启,就会全部丢失 。因为容器的文件系统是分层的,你修改的是最上层的可写层,而这一层在容器删除后即消失。所以, exec 是调试利器,但不是持久化配置的手段。要永久修改,必须通过 Dockerfile 重新构建镜像,或者通过 -v 挂载外部配置文件。

4. 从单个容器到协作生态:Docker Compose 的编排艺术与避坑指南

docker run 可以启动一个容器,但现实世界的应用从来不是单打独斗。一个典型的 WordPress 站点,至少需要 WordPress(PHP+Apache)、MySQL(数据库)、phpMyAdmin(数据库管理工具)三个服务协同工作。如果用 docker run 一条条手动启动,你需要记住:

  • 三个容器各自的 --name
  • 三个容器之间复杂的 --link --network 配置
  • MySQL 容器必须先于 WordPress 启动,否则 WordPress 会因连接失败而崩溃
  • 每次重启,都要按正确顺序执行三条 docker run 命令

Docker Compose 就是为解决这个问题而生的。它用一个 YAML 文件( docker-compose.yml ),声明式地定义整个应用栈。

4.1 docker-compose.yml 的核心结构与字段解析

以下是一个精简但功能完备的 WordPress Compose 文件:

version: "3.8"

services:
  db:
    image: mysql:8.0
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: rootpass
      MYSQL_DATABASE: wpdb
      MYSQL_USER: wpuser
      MYSQL_PASSWORD: wppass
    volumes:
      - db_data:/var/lib/mysql
    networks:
      - wordpress_net

  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    restart: always
    ports:
      - "8081:80"
    environment:
      PMA_HOST: db
      PMA_PORT: 3306
    depends_on:
      - db
    networks:
      - wordpress_net

  wordpress:
    image: wordpress:latest
    restart: always
    ports:
      - "8080:80"
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_USER: wpuser
      WORDPRESS_DB_PASSWORD: wppass
      WORDPRESS_DB_NAME: wpdb
    volumes:
      - wp_data:/var/www/html
    depends_on:
      - db
    networks:
      - wordpress_net

volumes:
  db_data:
  wp_data:

networks:
  wordpress_net:
    driver: bridge

这个文件的每一部分都有其不可替代的作用:

  • version: "3.8" :指定了 Compose 文件的语法版本。3.8 是目前最稳定、功能最全的版本,支持 deploy 等高级特性。
  • services :定义了应用中的所有服务(容器)。每个服务( db , phpmyadmin , wordpress )都是一个独立的容器。
  • image :指定每个服务使用的镜像。这里 db mysql:8.0 wordpress wordpress:latest ,实现了服务间的解耦。
  • environment :为每个容器注入环境变量。注意 WORDPRESS_DB_HOST: db:3306 ,这里的 db 不是 IP 地址,而是 Compose 自动创建的 DNS 名称。Compose 会为每个服务名创建一个内部 DNS 记录,使得 wordpress 容器可以直接用 db 这个名字访问 MySQL 容器,无需知道其真实 IP。
  • volumes :定义了命名卷( db_data , wp_data )。这比 docker run -v 的匿名挂载更高级,因为它由 Compose 管理,删除整个栈时,数据卷可以被保留( docker-compose down -v 才会删除)。
  • depends_on :声明了服务启动的依赖关系。 phpmyadmin wordpress 都依赖 db ,意味着 Compose 会确保 db 容器先启动并进入 healthy 状态后,才启动其他两个。但这只是“启动顺序”,不保证 db 的 MySQL 服务已经完全初始化好。因此,WordPress 镜像内部其实有一个重试逻辑,会不断尝试连接 db:3306 ,直到成功。
  • networks :定义了一个名为 wordpress_net 的自定义桥接网络。所有服务都加入这个网络,它们之间可以通过服务名互相发现,而不会暴露在宿主机的 bridge 网络上,安全性更高。

4.2 Compose 的日常操作与“一键式”运维

有了 docker-compose.yml ,整个应用栈的生命周期管理变得极其简单:

  • docker-compose up -d :后台启动整个栈。Compos 会自动创建网络、创建卷、拉取镜像(如果本地没有)、启动所有服务。整个过程是幂等的,多次执行效果相同。
  • docker-compose ps :查看栈内所有服务的状态,比 docker ps 更聚焦。
  • docker-compose logs -f wordpress :只查看 wordpress 服务的日志, -f 实现实时跟踪。
  • docker-compose down :优雅地停止并删除所有服务容器。 注意:这不会删除 volumes 中定义的数据卷 ,所以你的数据库和网站文件是安全的。
  • docker-compose down -v :停止并删除容器, 同时删除所有关联的数据卷 。这是彻底清理的命令,慎用。

一个关键的避坑经验: 永远不要在 docker-compose.yml 中使用 latest 标签作为镜像版本 wordpress:latest 看似方便,但当你几个月后再次 docker-compose up ,拉取的可能是 PHP 8.3 的新版 WordPress,而你的主题或插件可能不兼容,导致站点白屏。最佳实践是锁定具体版本,如 wordpress:6.3-php8.2-apache 。这样,你的 docker-compose.yml 就成了一个精确的、可复现的“应用蓝图”。

5. 从入门到进阶:常见问题排查速查表与我的实战心得

在带团队做 Docker 培训的三年里,我整理了一份高频问题排查速查表。这些问题,90% 都源于对 Docker 底层原理的模糊认知,而非操作失误。下面是我亲身踩过、并反复验证过的解决方案。

问题现象 根本原因 排查命令 解决方案 我的实战心得
docker: command not found Docker CLI 未正确安装或 PATH 未配置 which docker 重新安装 Docker CLI,或手动将 /usr/bin (Linux)或 C:\Program Files\Docker\Docker\resources\bin (Windows)加入系统 PATH 这个错误在 macOS 上最常见,因为 Homebrew 安装的 Docker CLI 和 Docker Desktop 自带的 CLI 会冲突。我的做法是: 卸载 Homebrew 版,只用 Docker Desktop 自带的 CLI ,并确保 which docker 返回的是 /usr/local/bin/docker
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? Docker 守护进程( dockerd )未启动 sudo systemctl status docker (Linux), docker info (macOS/Windows) Linux: sudo systemctl start docker ; macOS/Windows: 重启 Docker Desktop 应用 这个错误在 Linux 上,往往是因为你忘了 sudo 。但更深层的原因是: Docker 守护进程是以 root 用户身份运行的,普通用户无法直接与之通信 。正确的长期方案是: sudo usermod -aG docker $USER ,然后注销重登。但切记: 这相当于给了该用户 root 权限,切勿在生产服务器上为非运维人员添加此组
Error response from daemon: Conflict. The container name "/my-app" is already in use. 容器名冲突,同名容器已存在(即使已停止) docker ps -a | grep my-app docker rm my-app 删除已停止的容器,或 docker run --name my-app-new ... 换一个名字 这是新手最常犯的错误。 docker run --name 是强制唯一的。我的习惯是: 永远在 docker run 命令后加 --rm 参数 。这样,容器退出后会自动删除,彻底避免名字冲突。对于需要长期运行的服务,则必须用 docker-compose 来管理。
ERROR: for db Cannot create container for service db: invalid mount config for type "bind": bind source path does not exist -v 挂载的宿主机路径不存在 ls -la /my/host/path 在执行 docker-compose up 前,先手动创建好所有挂载路径: mkdir -p /my/host/path 这个错误在 docker-compose.yml 中尤其隐蔽。YAML 文件里的 volumes 字段,如果是相对路径(如 ./data:/var/lib/mysql ),它会相对于 docker-compose.yml 所在目录解析。我的经验是: docker-compose.yml 中,永远使用绝对路径 ,并在文档顶部加一行注释: # 所有路径均为绝对路径,如 /home/user/myapp/data
Pulling wordpress ... ERROR: Head "https://registry-1.docker.io/v2/library/wordpress/manifests/latest": dial tcp: lookup registry-1.docker.io on 192.168.65.1:53: read udp 192.168.65.2:50233->192.168.65.1:53: i/o timeout DNS 解析失败,无法连接 Docker Hub nslookup registry-1.docker.io 在 Docker Desktop 设置中(Settings → Docker Engine),修改 dns 配置为 ["8.8.8.8", "114.114.114.114"] ,然后点击 Apply & Restart 这个问题在国内几乎 100% 出现。很多人会去改宿主机的 /etc/resolv.conf ,但这对 Docker Desktop 无效,因为它的 DNS 是独立的。 最有效的方案,就是在 Docker Engine 的 JSON 配置中硬编码可靠的 DNS 服务器

最后再分享一个小技巧:如何快速查看一个镜像里到底有什么? docker history <image> 会列出该镜像的所有构建层(layer)及其大小,帮你分析镜像臃肿的原因; docker inspect <image> 会输出该镜像的完整元数据,包括 Cmd (默认启动命令)、 ExposedPorts (暴露的端口)、 Volumes (声明的数据卷)等。这两个命令,是理解任何第三方镜像的“X 光机”,比任何网上的“菜鸟教程”都管用。

我在实际使用中发现,Docker 的学习曲线不是平滑上升的,而是阶梯式的。前两天,你会觉得“不过如此,就是几个命令”;第三天,当你第一次成功用 docker-compose 启动一个三容器应用,并且数据还能持久保存,那种掌控感会让你兴奋得睡不着;再往后,当你开始写自己的 Dockerfile ,为公司内部项目定制基础镜像,你才真正理解了“一次构建,处处运行”的力量。这个过程没有捷径,但每一步的验证,都是在加固你对现代软件交付基础设施的理解。

更多推荐