ARTICLE DETAIL

资讯详情

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

Docker入门实战:从安装部署到Compose编排的整套指南

Docker入门实战:从安装部署到Compose编排的整套指南 最近看到很多人都在聊 Docker不少新手一上来就被镜像、容器、数据卷这些概念绕晕装个 Docker Desktop 还会碰到虚拟化报错干脆就说“搞不懂放弃了”。其实容器化没有想象中那么玄乎它解决的就是那个著名的“在我电脑上是好的”问题把你写的程序连同整个运行环境打包成一个标准单元拿到哪里都能原样跑起来。这篇我打算用最直白的方式带你把 Docker 从安装到实战走一遍。内容覆盖了 Windows 和 Linux 的安装、镜像加速、常用命令、用 MySQL 8.0 做第一个实战最后用 Docker Compose 拉起一整套环境再附上高频报错的排查笔记。适合完全没有容器经验的小白也适合被各种报错折磨到想放弃的新手。1. 先搞明白一件事容器到底是什么为什么人人都提它1.1 用租房类比理解镜像、容器和仓库Docker 里有三个最核心的概念镜像、容器、仓库。很多人记不住三者的关系我用租房子来打个比方。镜像是“户型图加装修方案的完整模板”是一个只读的静态文件包含了程序运行所需的操作系统底层库、代码、依赖和配置。你拿到一个镜像就等于拿到一套精心设计好的房屋模型。容器是基于镜像创建出来的“实际居住的房屋”是镜像运行时的实例。同一个镜像可以创建多个容器彼此隔离互不干扰。你可以随时停止、删除、重建容器容器里的数据如果不特殊处理删除后就没了。仓库是存放镜像的“楼盘平台”大家把自己的镜像传到仓库里供别人使用。docker pull 就是从仓库把镜像拉取到本地docker push 是把本地镜像上传到仓库。举个例子你运行docker run nginx系统先从仓库下载 nginx 镜像然后基于这个镜像创建出一个运行中的容器这个容器里就是一个完整的、已经启动好的 nginx 服务。整个过程像极了拿到装修模板后直接拎包入住。1.2 容器和虚拟机到底有什么区别虚拟机走的是硬件虚拟化路线它通过 Hypervisor 在物理主机上虚拟出完整的操作系统每个虚拟机都自带一套完整的 OS 内核。好处是隔离性极强坏处是重量级一个虚拟机往往要占好几个 GB 的磁盘启动以分钟计。容器走的是操作系统级虚拟化路线它直接共享宿主机的操作系统内核只是在用户空间做了隔离。每个容器就像操作系统中一个被圈起来的高墙院子里面的进程看起来是独立运行的但底层用的是同一个内核。这样的设计带来了一个非常直观的差别容器镜像小。一个精简的 Alpine Linux 镜像才几 MB一个带完整运行时的 Python 镜像也就几百 MB。容器启动以毫秒或秒计资源占用远低于虚拟机。当然容器不是万能的。因为共享宿主机内核容器天然不适合运行一个异构的内核比如不能在 Linux 宿主机上直接跑一个 Windows 内核的容器。虚拟机没有这个限制。1.3 为什么“环境一致”如此重要团队协作中最常出现的场景是开发在本机跑得好好的测试环境一部署就挂查了半天发现是依赖版本不一致、系统库缺失、配置文件路径对不上。Docker 把程序、依赖、配置、运行环境都固化在镜像中开发在容器里调试通过后测试和线上拉取同一个镜像运行结果必然一致。部署从“走流程配环境”变成了“拉镜像启动容器”两个动作这不仅是操作上的简化更是交付方式的改变。镜像一旦构建完成你的交付物就是一个标准制品和源代码分离管理。线上出问题需要回滚时直接把容器切回旧镜像即可几秒钟完成不再需要重新安装依赖、修改配置。2. 安装 Docker 的正确姿势Windows 与 Linux 的不同路线2.1 Windows 下安装 Docker Desktop 的准备工作Windows 上目前主流方案是安装 Docker Desktop它提供图形界面和一个完整的容器运行环境。安装前必须满足几个硬性条件缺一个都会导致启动失败。第一系统需要是 64 位的 Windows 10/11 专业版、企业版或教育版家庭版也能装但配置 WSL2 时的步骤会多一些。第二必须在 BIOS/UEFI 中开启硬件虚拟化这个是老生常谈但翻车率最高的一步。第三安装过程会启用 WSL2建议提前在管理员 PowerShell 里执行wsl --install完成内核更新。打开任务管理器切到“性能”标签页找到 CPU 一栏。如果看到“虚拟化已启用”说明硬件虚拟化已经开启如果显示“已禁用”需要重启进 BIOS找到 Intel Virtualization Technology 或 AMD SVM Mode改为 Enabled。安装包直接去 Docker 官网下载 Docker Desktop Installer安装过程中勾选“Use WSL 2 Instead of Hyper-V”选项。这里我明确推荐 WSL2 方案它比旧的 Hyper-V 方案资源占用更小启动速度更快。2.2 遇到 virtualisation support not detected 怎么办这是 Docker Desktop 在 Windows 上启动失败时最典型的报错完整信息是“Docker Desktop failed to start because virtualisation support wasnt detected or isnt enabled”。碰到这个问题按以下顺序排查在任务管理器 性能 CPU 中查看“虚拟化”状态如果显示“已禁用”进 BIOS 开启。确认“Windows 虚拟机监控程序平台”功能已启用控制面板 程序 启用或关闭 Windows 功能。以管理员身份运行 PowerShell执行systeminfo在输出中寻找 Hyper-V 要求的四项是否全部为“是”。如果已经安装了 WSL2 但 Docker 仍然报错可以尝试卸载 Docker Desktop 后重启再重新安装因为 WSL2 内核和 Docker 的集成会在安装时自动配置。有一次我在一台 i5 的老机器上遇到同样报错BIOS 里虚拟化明明是开启的折腾半天发现是系统里装了一款第三方安全软件干扰了 WSL2 的虚拟化平台初始化。卸载后重启就正常了。这种非标准情况排查起来很烦建议先把基础项排完再考虑软件冲突。2.3 Ubuntu 和 CentOS 的安装与权限配置Linux 下安装 Docker 不需要 Docker Desktop直接安装 Docker Engine 即可。Ubuntu 上我用得最多的是官方 apt 仓库方式先更新索引然后安装一些前置依赖再添加 Docker 官方 GPG 密钥和仓库。sudo apt update sudo apt install ca-certificates curl gnupg lsb-release添加仓库后安装sudo apt update sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-pluginCentOS 7 的步骤类似只是包管理器换成了 yum。CentOS 7 上有两个坑一是内核版本最好不低于 3.10旧内核可能在某些存储驱动上出问题二是安装完成后需要sudo systemctl start docker和sudo systemctl enable docker确保服务启动并设置开机自启。安装完成后执行docker --version验证。如果要用普通用户直接操作 Docker需要把用户加入 docker 用户组sudo usermod -aG docker $USER newgrp docker这里有个安全提示值得记住docker 用户组的权限非常大相当于授予了该用户 root 级别的控制能力。因为是利用 Docker 的守护进程以高权限执行容器实际上等同于拿到宿主机 root。所以在多人服务器上添加用户到 docker 组时需要确认对方是可信的。2.4 镜像下载太慢给 Docker 配个加速地址默认从 Docker Hub 拉取镜像在国内环境经常慢到怀疑人生一个几百 MB 的镜像可能要等十几分钟。解决办法是通过 daemon.json 配置 registry-mirrors 加速地址。Linux 上的配置文件路径是/etc/docker/daemon.json没有就手动创建{ registry-mirrors: [https://docker.m.daocloud.io] }修改后重启 Dockersudo systemctl daemon-reload sudo systemctl restart dockerDocker Desktop 用户可以在 Settings Docker Engine 中直接编辑 JSON 配置然后在界面右下角点击 Apply Restart。配置完成后用docker info搜索 Registry Mirrors 字段如果能看到你填写的地址说明加速生效。拉取镜像时建议用docker pull命令验证一下实际速度不同加速地址在不同网络的延迟差异比较大实测不行就换一个。3. 第一个容器镜像管理、启动参数和日志操作3.1 拉取镜像随手练先跑通再管细节安装完成后的第一个动作通常是把 hello-world 拉下来跑一遍docker pull hello-world docker run hello-world如果看到一串英文说明正常运行恭喜你Docker 的整个链路已经通了。但 hello-world 实在太简单感受不到实际价值。我建议直接拉一个完整的镜像同时熟悉镜像管理命令。docker search nginx docker pull nginx docker imagesdocker images会列出本机已有的镜像包含仓库名、标签、镜像 ID、创建时间和体积。这里有一个高频踩坑点当提示镜像的 Tag 是 latest 时不代表它一定是最新版。latest 只是一个标签维护者可能把它打在任何版本上。生产环境拉镜像强烈建议显式指定版本比如nginx:1.25.3这样镜像的确定性更高。拉镜像报错pull access denied通常是镜像名打错了或者该镜像是私有库的需要先docker login。还有个常见错误no space left on device说明 Docker 数据目录所在的磁盘满了后面会专门讲清理。3.2 docker run 的参数看不懂就白学了docker run是 Docker 里最重要的命令没有之一。新手最需要掌握的五个参数-d后台运行、-p端口映射、--name容器命名、-v数据卷挂载、-e环境变量。docker run -d --name my-nginx -p 8080:80 nginx拆开来看-d让容器在后台运行不占用当前终端--name my-nginx给容器起个名字方便后续操作-p 8080:80把宿主机的 8080 端口映射到容器的 80 端口这样浏览器访问http://localhost:8080才能到达容器内的 nginx。端口映射是个理解容器网络的好切入口。容器有自己独立的网络命名空间默认情况下外部访问不到容器的 IP。打个比方容器就是一个带围墙的院子-p相当于在围墙上开了一扇门宿主机 8080 这个门牌号直通院内 80 号房间。-e用来传入环境变量在部署 MySQL、Redis 这类需要通过环境变量初始化的镜像时非常常用。还有一个容易被忽略的--restart参数用它设置容器的重启策略。生产环境中我常配--restart unless-stopped意思是容器意外退出时自动重启除非是被手动 stop。3.3 查看日志和进入容器排障的基本功容器跑起来了怎么确认它工作正常怎么排查问题两个命令掌握就能应对大多数场景。查看日志docker logs my-nginx docker logs -f my-nginx-f是 follow 的意思持续跟踪日志输出类似tail -f。调试时我经常先docker logs -f挂着然后在另一边操作服务实时观察输出。进入容器内部docker exec -it my-nginx bash这个-it由-i和-t组合而成-i保持标准输入打开-t分配一个伪终端。进去之后可以像在一台独立服务器里一样执行命令、查看文件。退出执行exit。这里提醒一个常见错误不是所有镜像都自带 bash有些精简版镜像只有 sh。如果docker exec -it 容器名 bash提示 bash 不存在换成sh就能进了。查看所有容器状态docker ps docker ps -adocker ps只显示运行中的容器docker ps -a连已停止的也显示。这个区别非常关键很多新手排查问题的时候只看docker ps发现列表是空的就以为容器没建成功其实容器已经退出了。4. 实战用容器部署 MySQL 8.0还得保证数据不丢4.1 一条命令启动 MySQL 8.0MySQL 是一个适合做入门实战的镜像因为它涉及环境变量、端口映射、数据持久化、配置文件挂载全部关键点。docker run -d \ --name mysql8 \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORD你的密码 \ -v mysql_data:/var/lib/mysql \ mysql:8.0逐个说参数mysql8是容器名3306:3306把宿主机的 3306 端口映射到容器 3306MYSQL_ROOT_PASSWORD是初始化 root 用户密码时必需的环境变量-v mysql_data:/var/lib/mysql是数据卷挂载把它单独拎出来详细讲。执行完成后用docker ps查看容器状态等待几秒后执行docker logs mysql8查看初始化日志。看到ready for connections字样说明 MySQL 已经启动完成。4.2 数据卷容器删了数据还在默认情况下容器内的文件是临时存储容器删除后数据全部消失。想保存数据库文件必须用数据卷挂载。-v mysql_data:/var/lib/mysql的意义是宿主机上一个名为mysql_data的 Docker 命名卷被挂载到容器内的/var/lib/mysql目录MySQL 写入的数据实际落在宿主机的卷中。即使容器被删除卷里的数据依然保留。验证方法很直观docker stop mysql8 docker rm mysql8 docker run -d --name mysql8-new -p 3306:3306 -e MYSQL_ROOT_PASSWORD你的密码 -v mysql_data:/var/lib/mysql mysql:8.0重新启动一个容器挂载同一个数据卷之前建的数据库和表都还在。这种“容器可销毁数据得永生”的模式正是 Docker 在生产环境中的主要用法。除了命名卷还有绑定挂载方式-v /宿主机绝对路径:/容器内路径。比如把配置文件放在宿主机再挂载到容器内这样改配置不用进容器。这个方式在调试阶段特别方便改完宿主机文件重启容器即可生效。4.3 联网验证与字符集设置MySQL 启动后先用宿主机工具验证连接。如果在同一台机器上直接docker exec -it mysql8 mysql -uroot -p输入密码进入 MySQL 命令行执行SELECT VERSION(); SHOW VARIABLES LIKE character%;MySQL 8.0 默认字符集是 utf8mb4一般不需要额外设置。如果你从老项目迁移过来需要统一设置为 utf8mb4可以在启动时加参数--character-set-serverutf8mb4 --collation-serverutf8mb4_unicode_ci这里有个真实踩过的坑如果用 Navicat 或其他图形工具连接不上先检查宿主机防火墙是否放行了 3306 端口再用docker logs mysql8看看有没有异常。还有一个容易忽略的问题——如果宿主机 3306 已经被本地 MySQL 占用端口映射-p 3306:3306会失败报错信息里会提到 bind 失败换成-p 3307:3306就能解决。4.4 用 Dockerfile 打包自己的应用镜像部署第三方软件只是基础能力Docker 真正强大的地方在于把自己的应用打包成镜像。以一个 Node.js 应用为例FROM node:18-alpine WORKDIR /app COPY package*.json ./ RUN npm install --registryhttps://registry.npmmirror.com COPY . . EXPOSE 3000 CMD [node, app.js]构建命令是docker build -t my-app:v1 ..dockerignore文件千万别漏写。它和.gitignore作用类似把node_modules、dist、*.log这些不该进镜像的文件排除掉既能控制镜像体积又能避免构建上下文过大导致构建速度变慢。一次构建时忘了加.dockerignore几百 MB 的 node_modules 全被塞进构建上下文整个过程卡了十几分钟。5. Docker Compose一条命令拉起整套环境5.1 为什么需要 Compose一个复杂的项目往往需要多个容器配合前端、后端、数据库、缓存。如果全用docker run一条条写命令不但长到崩溃而且重启服务器后要手动再敲一遍容易漏。Docker Compose 通过一个 YAML 文件声明整套服务每个服务需要什么镜像、什么端口、什么依赖关系全部写进配置里。之后只需要docker compose up -d一条命令整套环境就拉起来了。5.2 先从一个 MySQL Redis 组合开始创建一个项目目录在目录下新建docker-compose.ymlversion: 3.8 services: mysql8: image: mysql:8.0 container_name: compose-mysql environment: - MYSQL_ROOT_PASSWORD123456 ports: - 3306:3306 volumes: - mysql_data:/var/lib/mysql restart: unless-stopped redis: image: redis:7-alpine container_name: compose-redis ports: - 6379:6379 command: redis-server --appendonly yes volumes: - redis_data:/data restart: unless-stopped volumes: mysql_data: redis_data:然后在目录下执行docker compose up -d-d表示后台运行。执行后 Docker 会检查本地有没有 mysql:8.0 和 redis:7-alpine 镜像没有就自动拉取然后创建并启动两个容器。查看状态docker compose ps停止服务docker compose down注意docker compose down默认不会删除数据卷所以数据还在。如果确实想把数据卷一起删掉要加-v参数这个操作不可逆除非确认数据无用否则别乱加。5.3 Compose 解耦配置与实战扩展Compose 还支持环境变量文件把密码、端口等可变内容抽出来放在.env文件中MYSQL_ROOT_PASSWORD123456 MYSQL_PORT3306YAML 里这样引用environment: - MYSQL_ROOT_PASSWORD${MYSQL_ROOT_PASSWORD} ports: - ${MYSQL_PORT}:3306这样做的好处是配置与编排文件分离。同一个 docker-compose.yml 可以在开发、测试、生产环境之间复用切换环境时只改.env即可。对于更复杂的场景比如部署一个内网穿透工具、代码托管平台或者一个完整的微服务应用Compose 同样适用。Team 里常见的做法是把所有容器编排逻辑统一维护在根目录的 docker-compose.yml 中新成员加入时拉取代码、复制.env.example为.env、修改必要配置、执行docker compose up -d环境就绪。这也正是容器编排相对于手工部署最大的效率提升。6. 高频报错与排查经验实录6.1 Docker Desktop 启动失败虚拟化和 WSL 相关报错Docker Desktop 在 Windows 上启动失败原因集中在以下三类。第一虚拟化未开启。表现为“virtualisation support wasnt detected or isnt enabled”处理方式是到 BIOS 开启 CPU 虚拟化再在 Windows 功能中启用“虚拟机监控程序平台”和“适用于 Linux 的 Windows 子系统”。第二WSL2 内核未更新。表现为提示关于 WSL2 的升级信息处理方式是在管理员 PowerShell 执行wsl --update第三WSL 发行版未安装或损坏。可以执行wsl --status和wsl --list --verbose检查。如果发行版状态异常或者根本没有发行版执行wsl --install -d Ubuntu安装完成并重启后再启动 Docker Desktop。6.2 npipe 连接失败Docker 服务没跑起来Windows 下使用命令行时经常遇到error during connect: failed to connect to the docker api at npipe:////./pipe/dockerdesktop-linux这个报错的含义是 Docker CLI 找不到 Docker 引擎。最常见的原因是 Docker Desktop 没有启动或者正在启动中。打开 Docker Desktop 等待鲸鱼图标不再动再重新执行命令。Linux 下对应的报错是/var/run/docker.sock: permission denied原因通常是当前用户不在 docker 组按前面说的执行sudo usermod -aG docker $USER并重新登录。如果服务本身没启动执行sudo systemctl start docker。还有一个很少人注意的点如果你是在 SSH 会话中加入了 docker 组需要重新建立 SSH 连接才生效单纯执行newgrp docker只在当前终端生效。6.3 镜像拉取失败与磁盘空间告急镜像拉取失败的典型提示包括pull access denied镜像名不存在或没有权限检查拼写私有镜像先docker login。EOF或TLS handshake timeout大概率是网络问题检查加速地址配置。no space left on device磁盘满了。用df -h确认磁盘占用然后清理docker system prune -adocker system prune -a会删除所有未被容器使用的镜像、停止的容器、未使用的网络和构建缓存。这个命令效果明显但很激进执行前最好确认没有需要保留的闲置镜像。只想清理构建缓存的话用docker builder prune想查看具体磁盘占用分布docker system df6.4 端口冲突与容器启动即退出的排查套路端口冲突的典型报错包含port is already allocated或bind: address already in use。处理思路要么换宿主机端口要么找到占用进程干掉。容器启动后立即退出的情况也很多见。排查步骤我建议固定成一个套路先看状态、再看日志、最后试交互式运行。docker ps -a docker logs 容器名 docker run -it --rm 镜像名--rm表示容器退出后自动删除专用于临时调试。日志是信息量最大的入口90% 的问题都能从日志里找到答案。如果日志没有输出可能是启动阶段就崩溃了这时候交互式运行可以直接看到进程报错。下面整理一个高频问题速查表建议收藏现象最可能的原因第一排查动作Docker Desktop 启动失败虚拟化未开启或 WSL2 异常检查 BIOS 虚拟化开关执行 wsl --statusnpipe 连接失败Docker Desktop 未启动启动 Docker Desktop 等待就绪permission denied用户不在 docker 组usermod -aG docker $USER镜像拉取超时网络问题或加速地址未配置检查 registry-mirrors 配置磁盘空间不足镜像和缓存堆积docker system prune -a端口绑定失败宿主机端口被占用换端口或用 netstat 找占用进程容器启动即退出启动命令异常或配置错误docker logs 容器名 查看输出无法进入容器镜像内没有 bash换成 docker exec -it 容器名 sh6.5 关于卸载重装和重置 Docker有时候问题排查太费时间直接卸载重装反而是最高效的方案。Windows 上卸载 Docker Desktop 之后最好把%AppData%\Docker和%LocalAppData%\Docker目录也删除避免旧配置干扰新安装。Linux 上卸载 Docker Engine 的套路是sudo apt purge docker-ce docker-ce-cli containerd.io sudo rm -rf /var/lib/docker/var/lib/docker是 Docker 默认的数据目录包括所有镜像、容器和数据卷。删除前必须确认里面没有需要保留的数据。想迁移 Docker 数据目录到其他磁盘可以在/etc/docker/daemon.json中配置data-root: /新路径/docker改完重启 Docker。新路径磁盘空间要充足否则容器一多照样爆盘。根据我的经验很多顽固的 Windows 虚拟化问题重置 WSL2 内核和重新安装 Docker Desktop 能解决大部分特别是升级系统后 Docker 突然起不来的情况卸载重装的效率往往高于慢慢查。7. 这条学习路线走下来你会收获什么按照这篇的顺序实际动手一遍你的收获会比看十篇教程更扎实。从理解镜像和容器的关系到亲手完成安装、配置加速、跑通第一个容器再到部署 MySQL 8.0、编写 Dockerfile、用 Compose 拉起整套环境每一步都是实际工作中最常用的操作。我个人的体会是学 Docker 最重要的一点不是追求一次把概念全弄懂而是先让东西跑起来再回头理解原理。很多人卡在安装阶段就放弃了其实大可不必。只要容器成功启动了一次那种“原来这么简单”的感觉会驱动你继续往下玩。后续遇到问题时多看看docker logs输出多查docker ps -a的状态多想一想容器删除后数据去了哪里这些基本动作足以帮你建立完整的容器排障直觉。最后再分享一个建议在个人电脑上专门建一个 docker 目录把你所有容器的 docker-compose.yml 和 .env 文件分项目存放。这样不管是迁移到新电脑还是恢复环境只要把目录拷过去、执行docker compose up -d之前辛苦搭建的环境几分钟就全部回来了。这个习惯我用了很久是实实在在提升效率的做法。容器化的世界很大Kubernetes、Service Mesh、Serverless 都在它之上生长但所有复杂体系都建立在镜像和容器这两个核心概念上。把基础打牢后面学什么都会顺很多。
返回列表