ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Docker安装实战指南:从环境认识到三大平台部署与避坑

Docker安装实战指南:从环境认识到三大平台部署与避坑 早些年装环境简直是我的噩梦。那时候项目要用 Redis、Nginx、Node、MySQL我老老实实一个个去官网下安装包然后配环境变量、改配置文件、处理端口占用最崩溃的是卸载不干净重装系统都试过两回。后来接触了 Docker才意识到过去那些折腾大部分都是在做无用功真正该装的是一个能装环境的容器。这篇是 Docker 系列的第 3 篇前两篇聊了容器技术的背景和基本概念这篇落到实操Docker 到底是什么、为什么值得装以及 Windows、macOS、Linux 三个平台从零到跑通hello-world的完整安装过程。文里所有步骤都是我在不同机器上实测过的也包括那些装完之后才发现的坑。无论你是刚接触 Docker 的开发者还是被各种环境折腾到怀疑人生的运维新人这篇都适用。1. 先搞清楚 Docker 到底解决了什么问题聊安装之前必须先把一个底层问题说透Docker 究竟在解决什么如果你不理解这个装完之后大概率只是多了一个吃内存的桌面软件然后继续用老办法装环境。1.1 环境隔离把污染挡在门外传统装环境的路子是直接在操作系统上装软件。今天装个 Python明天装个 Redis后天发现版本冲突然后开始漫长的卸载—清理—重装循环。更麻烦的是很多软件的依赖是全局共享的你在一个项目里升级了 OpenSSL另一个老项目可能就起不来了。Docker 的思路完全不同。它不修改你的宿主机而是提供一个隔离的运行环境。每个应用跑在一个独立的容器里容器里有自己的文件系统、网络接口、进程空间。应用以为自己在独享一台机器但实际上只是寄居在你的电脑里。这意味着你可以同时跑三个不同版本的 MySQL互不干扰你可以在容器里随便折腾坏了就删掉重建宿主机依然干干净净。1.2 一致性我这能跑你那儿不行从此消失另一个痛点就是环境差异。在我机器上能跑啊——这句话大概每个开发者都听过、也说过。你的机器是 Windows服务器是 CentOS你本地是 Python 3.9线上是 3.6你缓存了某些依赖线上没有。Docker 把应用连同它的运行环境一起打包成镜像。镜像里什么都带好了包括操作系统层、运行时、依赖库、应用代码。你本地怎么跑服务器上就怎么跑因为运行的就是同一个镜像。部署的时候只需要拉取镜像、启动容器不再需要在目标机器上重复一遍装环境的过程。1.3 秒级启动和快速销毁虚拟机也能做隔离但虚拟机要装完整操作系统启动要按分钟计算占用的资源也大。容器共享宿主机的内核启动本质上是创建一个进程所以启动速度是秒级的。我本机跑一个 Nginx 容器从命令执行到能访问大约 0.5 秒。开发时频繁创建、销毁环境这个体验差距是决定性的。这也回答了题图那个热搜词docker是干什么的——它本质上是一套标准化、可移植的软件打包与运行机制。你把它理解为一个装软件的规范盒子也行但记住盒子里不仅是软件还包括软件运行所需要的全部环境这才是它最厉害的地方。2. Docker 的三个核心概念镜像、容器、仓库很多人一上来就敲命令敲了半天还是晕就是因为没先搞懂三个基本概念。这里用生活化的说法把它们理顺。2.1 镜像Image只读的安装包模板镜像是一个只读的、分层构建的文件系统模板。你可以把它理解成一个软件快照里面包含了完整的运行环境和配置。docker pull nginx拉取的就是一个 Nginx 镜像。镜像有个很重要的特性分层。比如你写一个 Dockerfile基础镜像用ubuntu:22.04然后安装 Node 18再复制项目代码。这三步会形成三个层每一层都是基于上一层的增量。拉取的时候如果本地已经有ubuntu:22.04的层重复的层就不用再下载。这也是为什么 Docker 镜像传输比整机快得多因为很多层可以直接复用。2.2 容器Container镜像的运行实例容器就是镜像运行起来之后的活体。简单说镜像类似一个类容器就是类实例化的对象。同一个镜像可以创建多个容器每个容器都是独立运行的应用互不干扰。容器有一个特点可写层。容器运行时文件系统由两层组成底层是只读的镜像层上层是容器自己可写的。你在容器里修改的文件都存在可写层里一旦容器被删除这个可写层也一起消失。所以容器内产生的数据默认不持久化需要持久化的数据要用数据卷挂载。2.3 仓库Registry存放镜像的云盘仓库就是集中存放镜像的地方。最常用的是 Docker Hub它是一个公共的镜像仓库里面有官方维护的各类镜像。nginx、redis、mysql都有官方版本直接拉取即可。仓库的完整路径格式是[仓库地址]/[命名空间]/[镜像名]:[标签]。比如docker.io/library/nginx:latest其中docker.io是默认仓库地址library是官方镜像的命名空间。实际使用中经常省略默认地址和标签nginx默认等价于docker.io/library/nginx:latest。这三点连起来Docker 的核心流程就很清晰了从仓库拉取镜像用镜像创建容器容器里跑应用数据落到数据卷。后续所有的命令都是在围绕这四个动作展开。3. 环境安装前的准备先检查你的机器够不够格安装 Docker Desktop 之前有两件事必须先确认一个是操作系统版本和 CPU 架构另一个是虚拟化支持。别觉得这是小事很多装不上和装完启动失败的问题根源就在这里。3.1 操作系统和架构检查先看你的系统类型和 CPU 架构。打开终端执行# Linux / macOS uname -m # Windows PowerShell echo $env:PROCESSOR_ARCHITECTURE常见的输出有x86_64对应 Intel/AMD 的 64 位 CPU、aarch64对应 ARM64 CPU比如 Apple M1/M2/M3 芯片。这个信息决定了你要装哪一个版本的 Docker。macOS 用户要特别注意M 系列芯片和 Intel 芯片的镜像架构不一样。Apple Silicon 的 Mac 上Docker Desktop 默认会模拟 x86 环境但性能有损耗。新版 Docker Desktop 支持arm64原生镜像像mysql、redis这些官方镜像都有 arm64 版本拉取的时候 Docker 会自动选择匹配的架构。3.2 Windows 必须开虚拟化先跑一个自检命令Windows 上 Docker Desktop 依赖虚拟化技术底层要么是 Hyper-V要么是 WSL2。没开启虚拟化的话安装完会出现一个最经典的错误提示Docker Desktop failed to start because virtualization support wasnt detected.这个提示就是说你的电脑没有开启虚拟化功能。排查步骤如下先在 PowerShell 里输入systeminfo输出信息里找到 Hyper-V Requirements 部分。重点看两项Virtualization Enabled In Firmware固件中已启用虚拟化和 A hypervisor has been detected已检测到虚拟机监控程序。如果第一项显示No说明 BIOS/UEFI 里的虚拟化开关没打开。解决方案是重启电脑进入 BIOS 设置界面不同品牌进入方式不同大多数是开机按 F2 或 Del。在 BIOS 里找到Intel Virtualization TechnologyIntel或SVM ModeAMD把它设为Enabled保存退出。如果重启后systeminfo还是显示No可能是主板固件更新问题更新 BIOS 后再试。3.3 WSL2 检查Docker Desktop 的新依赖现在的 Docker Desktop 默认使用 WSL2 后端因为它的性能全面优于旧版 Hyper-V。装 Docker 之前建议先确认 WSL 是否可用wsl --status如果没有输出或者提示没有安装 WSL可以顺手装上。安装 Docker Desktop 的时候其实可以顺便处理但提前装好更省事。安装 WSL2 要分两步先启用 Windows 功能再设置默认版本。# 启用 Windows 子系统 Linux 和虚拟机平台功能 dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart执行完后重启电脑。重启后在 PowerShell 里设置默认版本wsl --set-default-version 2这里有一个容易忽略的坑WSL 内核必须更新。如果系统比较旧执行上面命令可能会提示需要更新 WSL 内核。解决办法是去微软官网下载最新的 WSL2 Linux 内核更新包安装后重新执行wsl --set-default-version 2。3.4 macOS 的准备工作相对简单macOS 上 Docker Desktop 的要求是macOS 12 或更高版本至少 4GB 内存。如果是 Apple Silicon 芯片系统版本要求会更高一点。没有额外的虚拟化开关需要打开因为 macOS 自带的 Hypervisor.framework 已经提供了支持。唯一的槽点是老款 Intel Mac 跑 Docker Desktop 普遍存在资源占用高的问题4GB 内存会比较紧张建议 8GB 起步。4. 三个平台的 Docker Desktop 安装实操准备做完了下面进入正题。我按 Windows、macOS、Linux 三条线来走一遍同时会讲清楚每一步是为什么这么做而不只是给一串命令。4.1 Windows下载、安装、切换 WSL2 后端Docker Desktop 的安装包要从 Docker 官网下载搜索 docker desktop download认准docker.com后缀。拿到.exe安装包后双击运行基本就是一路 Next。安装过程中有个复选框会问你是否使用 WSL2 作为后端。建议勾选 WSL2因为现在 Docker Desktop 已经不对 Hyper-V 做重点优化了。装完之后的配置要分两处确认第一处是 Docker Desktop 的 Settings → Resources → Advanced确认 WSL Integration 已经启用第二处是在 PowerShell 里确认默认 WSL 版本是 2wsl --list --verbose如果默认版本不是 2用下面命令指定wsl --set-default-version 2这里给一个非常容易踩的坑如果你之前装过 WSL1 的发行版WSL2 可能不会自动生效。当时我遇到的情况是wsl --list --verbose显示我的 Ubuntu 还是 VERSION 1Docker Desktop 启动时直接提示无法连接到引擎。解决方法是# 停掉旧的 WSL 实例 wsl --shutdown # 把发行版迁移为 WSL2 wsl --set-version Ubuntu 2迁移完成后重新验证Docker Desktop 就能正常启动了。4.2 macOSIntel 与 Apple Silicon 的差异macOS 上安装 Docker Desktop 最简单下载.dmg文件双击打开把 Docker 图标拖到 Applications 文件夹然后再双击运行。首次启动会要求授权安装辅助工具并输入密码这是 Docker Desktop 在配置权限属于正常现象。接下来一个关键选项Apple Silicon 和 Intel 版本的 Docker Desktop 是不同的安装包。官网下载页面会自动识别你的芯片但如果你手动寻找版本一定不要下错。对于 Apple Silicon还有一个小优化Docker Desktop 默认会为容器分配一部分内存。M 系列芯片的内存是统一的统一内存架构所以分配给你的可用内存直接影响 Docker 内应用的体验。我建议在 Settings → Resources 里把内存调到 4GB 以上如果只是跑轻量应用 2GB 也够但跑多个容器会明显卡顿。4.3 Linux优先用发行版软件源但版本会老Linux 上没有 Docker Desktop 那样的一体化安装包虽然现在也有了但体验一般更常用的是安装 Docker Engine。以 Ubuntu 为例我推荐用官方 apt 源安装因为这样能保证跟着 Docker 的发布节奏升级。安装前的准备是卸载可能存在的旧版本sudo apt remove docker docker-engine docker.io containerd runc然后添加 Docker 官方 GPG key 和软件源# 安装 curl 和 ca-certificates sudo apt update sudo apt install -y ca-certificates curl # 下载并安装 GPG 密钥 sudo install -m 0755 -d /etc/apt/keyrings sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc sudo chmod ar /etc/apt/keyrings/docker.asc # 添加 docker 软件源 echo \ deb [arch$(dpkg --print-architecture) signed-by/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \ $(. /etc/os-release echo $VERSION_CODENAME) stable | \ sudo tee /etc/apt/sources.list.d/docker.list /dev/null接下来更新并安装sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin这里有三个细节提醒第一在docker-ce这个包名里ce是 Community Edition社区版。如果你用的不是 Ubuntu 而是 Debian系统代号要相应调整Debian 12 对应的是bookworm。第二添加源那一段的$(. /etc/os-release echo $VERSION_CODENAME)会自动取系统代号但如果你的 Ubuntu 是 LTS 版本这个变量不会准确对应 Docker 支持的源名称。比如 Ubuntu 24.04 的代号是nobleDocker 官方源在某个阶段可能还没有noble目录这时候要手动把源改成jammy22.04 代号来兼容。第三也是很多新手挂在半路的问题下载速度极慢。Docker 官方源在一些网络环境下访问很慢apt update 可能要等好几分钟。这时候可以用阿里云、清华等镜像站替换官方源速度快很多。具体做法是把download.docker.com换成对应镜像站的地址GPG key 也可以从镜像站获取。4.4 Linux 下免 sudo配置最值得做的一步装完之后你会发现每次执行docker命令都要加sudo很烦。这个问题的根源是 Docker 的守护进程dockerd需要 root 权限而docker命令要与守护进程通信默认需要走/var/run/docker.sock这个 socket 文件它属于 root 用户和 docker 组。解决办法是把当前用户加入 docker 组sudo groupadd docker || true sudo usermod -aG docker $USER然后重新登录一次或者执行newgrp docker让用户组生效。之后就能直接用了docker version这一步有个安全提示需要注意加入 docker 组的用户相当于获得了 root 权限因为 Docker 可以挂载宿主机目录进容器。所以只对你信任的账号做这个操作不要随手把所有用户都加进去。5. 安装完成后的验证与关键配置环境装好之后下一个动作是验证、配置镜像加速、处理权限问题。这一节我按从验证到踩坑的顺序来展开。5.1 验证 Dockerhello-world 是怎么工作的先跑一个最简单但也最经典的测试docker run hello-world这条命令背后发生了四个动作检查本地有没有hello-world镜像没有就拉取创建容器运行容器退出容器。如果输出里出现 Hello from Docker!说明安装成功。这里有个小知识hello-world镜像本身只有几 KB它什么都不复杂只打印一段欢迎语。它的价值在于验证 Docker 的拉取、创建、运行整条链路是否正常。如果你能看到那段欢迎语说明 Docker 引擎、网络、CLI 都没问题。如果拉取镜像时报错常见的提示有Error response from daemon: Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting for connection这个基本就是网络问题。Docker Hub 在国内访问不稳定解决办法是配置镜像加速器。5.2 配置国内镜像加速解决下载慢镜像加速的作用是代理拉取 Docker Hub 上的镜像。配置方式在 Docker Desktop 和 Docker Engine 里不一样。Docker Desktop 用户打开 Settings → Docker Engine在registry-mirrors字段里填入加速地址然后点 Apply Restart。{ registry-mirrors: [ https://docker.mirrors.ustc.edu.cn, https://hub-mirror.c.163.com ] }Docker EngineLinux用户编辑/etc/docker/daemon.json文件如果没有就新建sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json EOF { registry-mirrors: [ https://docker.mirrors.ustc.edu.cn, https://hub-mirror.c.163.com ] } EOF然后重启 Dockersudo systemctl daemon-reload sudo systemctl restart docker验证生效的方式是执行docker info看看输出里的Registry Mirrors一栏是否列出了你配置的地址。需要提醒的是镜像加速并不能加速所有镜像。不少镜像尤其是需要从 GitHub Releases 下载内容的自定义镜像在构建时才真正拉取外部文件加速只覆盖了 Docker Hub 相关的层。如果你拉某个镜像仍然很慢可以先看看是不是这个镜像本身在构建时依赖外部网络。5.3 启动失败的经典错误virtualization support wasnt detected前面在准备阶段提过一次但这个错误出现频率实在太高值得单独列出完整的排查路径。症状是双击 Docker Desktop 后弹窗提示启动失败错误信息包含virtualization support wasnt detected。第一步确认 Hyper-V 功能和虚拟机平台是否启用。在管理员身份的 PowerShell 里执行Get-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V Get-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform如果 State 不是 Enabled就启用。第二步如果功能已启用但还是报错问题可能出在 BIOS 里虚拟化开关没开。上面说过了进 BIOS 找到 Intel VT-x 或 AMD SVM 开启。第三步如果 BIOS 也开了错误依旧还有一个隐藏原因——有旧版 Hyper-V 与 WSL2 冲突。这种情况下打开 Windows 功能 面板找到 Hyper-V 和 Windows 虚拟机监控程序把两个都关掉重启再尝试启用 WSL2。我处理过一台老笔记本就是最后这个原因。它的 BIOS 虚拟化开关是一开始就开着的但 Docker Desktop 还是报错排查最后发现是 Windows 上残留的旧 Hyper-V 组件和 WSL2 打架。关掉旧组件、只保留 WSL2 之后问题才彻底解决。5.4 权限报错permission denied while trying to connect to the Docker API我在 Linux 上第一次跑docker ps的时候就被这个报错糊了一脸permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/json: dial unix /var/run/docker.sock: connect: permission denied这个报错有两种解法。第一种是把用户加入 docker 组上一节已经写了。第二种是临时授权适合只想跑一条命令的情况sudo docker ps但我强烈不建议一直用sudo docker理由不只是麻烦还有安全性的问题sudo会让 root 用户直接操作 socket日志会记录异常权限更关键的是如果哪个脚本里混了一条docker run命令而它恰好是恶意的那这个恶意容器默认挂载的是 root 权限的目录。正确解法始终是把普通用户加入 docker 组之后平时操作再也不用 sudo。这个报错的根因其实不是权限设置错误而是用户不属于 Docker 运行所需的权限组。理解这一点以后换机器也不会慌。6. 跑通 hello-world 之后第一次实战的避坑清单环境装好了、验证通过了接下来才是 Docker 真正开始发挥作用的地方。这里集中整理我在初学阶段踩过的、以及不少读者反馈过的坑按从安装到日常使用的顺序列出来你可以直接当参考手册用。6.1 启动容器时的端口占用问题第一次跑 Nginx 容器很多人会这样操作docker run -d -p 8080:80 nginx然后发现宿主机上访问http://localhost:8080没反应。排查思路先确认容器状态docker ps发现容器状态是 Exited再去查日志docker logs 容器ID过半的情况是 80 端口在容器内已经占用或者宿主机的 8080 端口被别的进程占用了。解决方法是换个宿主端口比如-p 8081:80。还有一个隐蔽的坑如果宿主机上有什么服务已经在监听 80 端口而你把容器端口映射也写成了80:80启动会报端口冲突。这个在 Windows 上尤其常见因为 IIS 默认占用 80。6.2 容器内文件修改不生效数据卷的概念初用 Docker 时我改了一份容器里的配置文件然后docker stopdocker start发现改动全没了。原因是容器停止不丢数据但删除容器时可写层被一并移除。如果你在容器里直接修改文件而这些文件本身来自镜像层那它们只存在于容器的可写层容器一删改动就没了。正确的做法是用数据卷Volume把宿主机目录挂进容器docker run -d -p 8080:80 -v /home/me/nginx/html:/usr/share/nginx/html nginx这样/home/me/nginx/html里的文件就直接映射到容器的目录里你在宿主机改什么容器内立刻生效容器删除后数据也不会丢。6.3 网络问题容器之间怎么通信还有一个常见困惑为什么两个容器之间无法通过 localhost 访问原因是每个容器默认有自己独立的网络栈localhost只代表容器本身。想要容器间通信需要把他们放在同一个自定义网络里docker network create my-net docker run -d --network my-net --name app1 nginx docker run -d --network my-net --name app2 redis这样容器之间可以通过容器名互相访问比如在 app1 里访问app2:6379。这个机制叫 Docker 自定义网络以后你做多容器应用比如前后端 数据库时一定会用到。热词里出现过的docker网络不通多数时候就是容器不在同一个网络里或者宿主端口映射没映射到正确的容器端口。排查命令先把网络列表看一遍docker network ls docker network inspect my-net把容器放进同一个网络后通信问题通常立刻消失。最后再分享一个实际体会跑通 hello-world 那一刻只是 Docker 入门的第一步真正的收获在之后当你用 Docker 把开发环境的数据库、缓存、队列全部容器化然后换一台新电脑时执行几条命令一分钟内重建出完全一致的环境那种终于不用再折腾了的感觉值得你花这几十分钟把基础打好。如果这篇文章帮你装好了 Docker下一步我建议做两件事第一把常用的数据库镜像比如mysql:8.0拉下来跑一个带数据卷的实例感受一下数据持久化第二尝试用 Docker Compose 编排一个简单的 Nginx Redis 服务组。这两个场景覆盖了 Docker 日常使用的大部分需求掌握了它们你已经比大部分装完就吃灰的用户走得远多了。
返回列表