如果你搜到“如何装docker”,多半是遇到了环境问题:本地跑得好好的代码,换台机器就崩,或者看中一个开源项目,光装依赖就折腾一下午。Docker就是来终结这种痛苦的,它把应用连同运行环境一起打包成镜像,一条命令就能在任何装有Docker的机器上跑起来。这篇文章不绕理论,直接从零开始,覆盖Windows和Linux两种主流平台的安装流程,包括安装前的系统要求、Docker Desktop与Docker Engine的选型、镜像加速配置、高频报错排查,最后用Docker Compose部署MySQL 8.0和Redis主从。适合第一次装Docker的新手,也适合装了但反复出问题的老手对照排查。
1. Docker是什么,为什么人人都在装
1.1 Docker解决的核心痛点
我见过太多人被环境问题劝退:代码在本地跑得好好的,发给同事死活跑不起来;服务部署到服务器上,缺一个运行库就折腾半天;同一台机器上要跑两个项目,一个要Python 3.10,一个要Python 3.8,互相打架。Docker解决的就是这种“环境地狱”。它把应用、运行库、配置、启动命令一起打包成镜像,运行时通过容器隔离,每个容器就是一个独立的小环境。装好Docker之后,部署一个软件通常只有两步:拉镜像、起容器,再也不用关心这台机器上装了什么、缺了什么。
这种“打包即交付”的方式,直接改变了协作方式。以前交付一个软件,要写安装文档、部署手册,还要祈祷客户环境和我的一样;现在交付一个镜像,对方只需要有Docker就能跑,版本一致、行为一致、连日志格式都一致。这也是为什么越来越多开源项目选择用Docker分发。
1.2 从“装环境”到“装应用”的思维转变
刚开始接触Docker的人,最容易卡在一个思路转换上:以前我们装软件,是“先准备系统环境,再安装软件,最后配置”;Docker反过来,你不需要关心系统环境,因为环境被封装在镜像里。你可以把镜像理解成一个集装箱,里面是你的应用和它需要的所有东西,Docker引擎就是集装箱码头上的吊车,不管集装箱里装的是什么,都能按要求放到指定的位置。
这个类比很实用。集装箱运输之所以能标准化,是因为箱子尺寸统一、接口统一,搬运流程不受货物类型影响。Docker也一样,镜像格式统一、容器运行时标准,所以同一个镜像可以在开发者的Mac、测试同学的Windows、生产服务器的Linux上以几乎一样的方式运行。差异不是完全为零,但被压缩到了极小范围。
1.3 装好Docker之后能干嘛
装好Docker之后,最常见的用途有两类。第一类是基础服务本地化,数据库(MySQL、PostgreSQL、Redis)、消息队列(RabbitMQ、Kafka)、搜索服务(Elasticsearch)这类依赖,用Docker一条命令就能起,不用在系统里装一堆东西,也免去了多项目版本冲突;用完直接把容器删了,系统干干净净。第二类是应用和平台,GitLab、Jenkins、Jellyfin、Nextcloud这类成套软件,以前配置繁琐,现在多数有官方镜像,一条命令加一个Compose文件就能完整拉起。还有搞CI/CD的,Docker是流水线里最常用的构建和运行环境。
另外,现在很多容器平台(Kubernetes、Rancher、K3s)都假设你已经了解了Docker的基本概念。即便你最终目标是上K8s,在本地装好Docker并用熟练,也是必经的第一步。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 安装前的准备:先看清你的系统再动手
2.1 Windows平台的硬性前提
如果你在Windows上装Docker Desktop,有几个前提必须提前确认,不然后续报错会非常痛苦。首先是系统版本,建议Windows 10 2004或更高,Windows 11最好;其次是CPU虚拟化,需要在BIOS里开启Intel VT-x或AMD-V,可以在任务管理器里提前看一眼,如果“性能”标签下的“虚拟化”显示“已启用”,说明BIOS层面没问题。然后是Windows功能,Docker Desktop的默认运行方式依赖WSL2,需要启用“适用于Linux的Windows子系统”和“虚拟机平台”两个功能。
这些前提缺一不可。我帮同事排查过“virtualization support not detected”的报错,最后发现是BIOS里虚拟化被关了;也遇到过系统功能开了,但WSL版本还是1,导致Docker Desktop反复崩溃。所以安装之前先花十分钟做检查,能省下后面好几个小时的排错时间。
2.2 Linux与macOS的安装通道
Linux装Docker,方式和Windows完全不一样。Linux上装的是Docker Engine,一个纯粹的后台服务,没有图形界面,通过命令行管理。主流的发行版各有各的安装方式:Ubuntu和Debian系用apt,CentOS和RHEL系用yum/dnf,openEuler这类发行版通常可以沿用RHEL系的安装思路,具体看官方文档。macOS实际上没有真正的原生Linux容器运行环境,官方提供的是Docker Desktop for Mac,它内部会跑一个轻量Linux虚拟机来提供容器能力;如果不喜欢Desktop,也可以用Colima加docker-cli的组合,但从易用性角度,新手更推荐Docker Desktop。
选择安装通道的本质,取决于你的使用场景。如果是个人电脑、主要用于本地开发,Windows/macOS请直接选Docker Desktop;如果是云服务器、生产环境、长期运行服务,请用Linux的Docker Engine,它更轻量、更稳定,也更适合被systemd管理。
2.3 Docker Desktop和Docker Engine到底怎么选
| 维度 | Docker Desktop | Docker Engine |
|---|---|---|
| 支持系统 | Windows、macOS | Linux |
| 界面 | 带GUI控制面板 | 纯命令行 |
| 自带Kubernetes | 内置,一键开启 | 不内置,需单独部署 |
| 系统资源占用 | 相对较高 | 相对较低 |
| 典型场景 | 本地开发调试 | 服务器生产部署 |
这里有个经常被忽略的点:Docker Desktop对大型企业有商业授权要求,个人使用和小型公司可以免费使用,但如果你所在公司规模比较大,使用前最好确认一下许可证政策。Linux上的Docker Engine本身是开源的,docker-ce和容器运行时containerd都遵循Apache 2.0协议,没有这类限制。
安装方案定了之后,还有一个统一建议:不管哪个平台,装完之后第一件事就是配置镜像加速,这直接影响你后续拉镜像的体验。具体做法放在第五章,先按顺序把安装流程走完。
3. Windows 11/10安装Docker Desktop全流程
3.1 启用WSL2和虚拟机平台
这里直接给一套可复制的操作。先以管理员身份打开PowerShell,执行:
powershell复制wsl --install
这条命令在Windows 11上会自动启用WSL2所需功能,并默认安装Ubuntu发行版。如果是老版本Windows 10,或者命令执行失败,就手动启用两个Windows功能:
powershell复制dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
重启之后,在PowerShell里把默认版本设为WSL2:
powershell复制wsl --set-default-version 2
如果提示“WSL 2 requires an update”,执行一下 wsl --update 更新内核。最后可以用 wsl --status 确认当前状态。这里多花几分钟检查,后面安装Docker Desktop就会顺很多。
3.2 下载、安装与首次启动
去Docker官网下载Docker Desktop Installer.exe,下载后双击运行。安装界面里有一个关键选项:是否使用WSL 2代替Hyper-V,强烈建议勾选WSL 2。原因很实际:WSL 2的启动速度更快、内存占用小一些,而且和Windows文件系统共享更自然。
安装完成后先别急着执行命令,启动Docker Desktop,等托盘图标稳定下来,不再闪烁旋转。首次启动可能会提示登录Docker账号,可以直接跳过,这不影响基础使用。真正验证安装是否成功的是命令行:
powershell复制docker --version
docker compose version
docker run hello-world
docker run hello-world 会拉取一个极小的镜像并运行,打印一段欢迎信息。这一步成功,说明引擎、网络、镜像拉取链路都通了,Docker Desktop基本算是装好了。
3.3 验证安装并配置镜像加速
如果 hello-world 卡在拉镜像那里半天没动静,多半是网络链路问题。这时打开Docker Desktop的Settings,切到Docker Engine,在JSON配置里加上registry-mirrors:
json复制{
"registry-mirrors": ["https://docker.m.daocloud.io", "https://docker.nju.edu.cn"]
}
点击Apply & Restart,等待引擎重启,再跑一次 docker run hello-world。这个配置会持久化,不用每次启动都设。关于镜像加速的更多细节和注意事项,第五章再展开。
还有一个细节值得提一句:Docker Desktop是英文界面,网上有一些汉化包,但我建议你直接适应英文。因为你真正高频使用的地方是命令行,命令本身没有中文界面,界面上偶尔几个英文按钮,用两天就习惯了。
4. Linux服务器安装Docker Engine
4.1 Ubuntu/Debian官方仓库安装
Linux下面装Docker Engine,最稳妥的方式是使用Docker官方仓库,而不是系统自带的旧版本。以Ubuntu为例,先装依赖,再添加官方GPG密钥和仓库:
bash复制sudo apt update
sudo apt install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
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
几个命令分开说明一下。curl那一步是把Docker的GPG签名导进来,目的是让apt校验软件包来源;echo那一步生成了docker-ce的软件源文件,里面的仓库地址会随Ubuntu版本自动替换成对应代号。如果你在云服务器上,curl访问官网源偶尔会失败或很慢,可以换成对应的云厂商镜像源,把download.docker.com替换成你云厂商提供的docker-ce镜像地址,后面的步骤完全一样。
4.2 CentOS/RHEL与衍生发行版安装
CentOS系的操作路径略有不同。先用yum-utils工具添加仓库:
bash复制sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
装完先启动服务:
bash复制sudo systemctl start docker
sudo systemctl enable docker
这里有一个容易踩坑的点:CentOS 7自带的内核版本较老,有些版本默认装了旧Docker或podman,新装的docker-ce可能和旧组件冲突。建议安装前先 yum remove docker docker-client docker-common docker-engine 清一遍残留。openEuler等RHEL衍生发行版,原则上可以参照这套流程,但要注意软件仓库和内核配套情况,最好优先用发行版官方文档说明的方式。
4.3 安装后必做的三件事
第一件事,把当前用户加入docker组,避免每次执行docker命令都要加sudo:
bash复制sudo usermod -aG docker $USER
改完需要重新登录终端才能生效。这一步不做也行,但做了之后体验会明显提升,不然你会一直撞上“permission denied while trying to connect to the docker daemon socket”。
第二件事,设置开机自启:
bash复制sudo systemctl enable --now docker
服务器重启之后Docker会自动起来,不至于半夜跑着跑着服务没了。
第三件事,验证。
bash复制docker version
docker run hello-world
docker version 要同时看到Client和Server两部分,如果只有Client没有Server,说明守护进程没起来,先查 systemctl status docker。hello-world跑通,说明镜像拉取和容器运行都正常,可以放心往下用了。
5. 镜像拉取慢的解决办法:配置镜像加速
5.1 加速原理与适用场景
Docker默认从Docker Hub拉镜像,这是全球最大的公共镜像仓库,但受网络链路和镜像仓库位置的影响,直接拉取公共镜像经常会出现速度慢、连接超时甚至中断的情况。镜像加速器的原理,是在国内部署一个Docker Hub的只读缓存或中转,你拉镜像时先访问它,由它去下载并缓存,再传给你。对你来说,命令还是Docker原生命令,只需要在配置里加一个镜像地址。
需要说清楚的是,镜像加速只解决“从Docker Hub拉公共镜像慢”的问题。如果你拉的是某些第三方平台的镜像,或者构建镜像时需要从其他源下载依赖,那属于另一个层面的问题,不在这里讨论。另外,公共加速器地址经常变动,本文提到的地址只作为示例,配置之前先访问服务商官网或实测连通性。
5.2 Linux下修改daemon.json
Linux上修改Docker守护进程配置文件:
bash复制sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://docker.nju.edu.cn"
]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
注意daemon.json是Docker守护进程的全局配置,JSON格式必须严格,行末不能有多余逗号。配完重启后,用 docker info 查看底部是否有Registry Mirrors列表,有就说明配置生效。
这里说一个很多人不知道的小技巧:配置多个加速器没问题,但Docker会按顺序尝试,第一个拉不到才会依次往后找,所以第一个地址请放你最信任的。实测下来,同一个地址上午好用下午超时的情况出现过不少次,所以不要把所有希望寄托在单一加速器上。
5.3 Windows/Docker Desktop配置方式
Windows上用Docker Desktop配置镜像加速更直观。打开Settings,选择Docker Engine,在JSON配置里修改registry-mirrors,点击Apply & Restart就生效。唯一区别是Docker Desktop会把这些配置合并到它管理的daemon.json里,不需要你手动去改文件路径。
配置完成后,我的习惯是用一个小镜像快速验证:
bash复制docker pull nginx:1.25
docker run -d --name test -p 8080:80 nginx:1.25
然后浏览器访问 http://localhost:8080,能看到nginx欢迎页就说明全链路通了。跑完把这个测试容器删掉,避免残留。
6. 装完Docker后最常用的命令
6.1 镜像管理命令
镜像管理是日常操作最频繁的一组命令。常用搜索:
bash复制docker search nginx
docker pull nginx:1.25
docker images
docker rmi nginx:1.25
docker pull 指定tag很重要,默认不加tag拉的是latest,但latest并不总是最佳选择,生产环境一定要锁定具体版本号。docker rmi 删除镜像前要确认没有容器还在使用,否则会报“image is being used by container”。如果想把本机镜像搬到另一台机器,用 docker save 导出tar包、docker load 导入:
bash复制docker save nginx:1.25 -o nginx.tar
docker load -i nginx.tar
这个方法在内网环境或离线环境非常实用,我部署离线项目时经常用。
6.2 容器生命周期命令
容器的核心命令可以用一条run命令包罗:
bash复制docker run -d --name web -p 8080:80 nginx:1.25
参数拆开看:-d是后台运行;--name给容器起名;-p把宿主机8080端口映射到容器80端口。如果容器启动后没起来,先看日志:
bash复制docker logs -f web
交互式进入容器内部用exec:
bash复制docker exec -it web bash
容器停止、启动、删除:
bash复制docker stop web
docker start web
docker rm -f web
需要特别提醒的是,docker rm -f 会直接删除容器,容器内的数据如果没有挂载卷也会一并消失。所以先想清楚再删,别手滑。
6.3 数据卷与网络基础
容器是临时的,数据不能放在容器内部,否则容器一删数据全没了。正确的做法是挂载数据卷或宿主机目录:
bash复制docker run -d --name mysql8 -v /my/data:/var/lib/mysql mysql:8.0
这里 -v /my/data:/var/lib/mysql 把宿主机目录挂进容器,数据写进宿主机,容器删了数据还在。网络方面,多个容器之间如果要互相访问,最推荐的方式是创建一个自定义网络:
bash复制docker network create app-net
docker run -d --name redis --network app-net redis:7
自定义网络的好处是容器之间可以直接用容器名做域名解析,比如另一个容器里访问redis,直接用“redis:6379”就行。默认的bridge网络没有DNS自动解析,生产级部署还是建议挂到同一个自定义网络里。
7. 实战:用Docker Compose部署MySQL 8.0与Redis主从
7.1 Docker Compose快速认知
Docker命令适合单容器操作,但一个完整项目往往有多个服务,比如后端、数据库、缓存、队列。每个服务都写一条docker run命令,既难记又难维护。Docker Compose就是来解决这个问题的,它用一个YAML文件描述所有服务,一条命令就能把整套环境拉起来。
Compose文件基本的骨架是services节点,每个服务对应一个容器,可定义镜像、端口、环境变量、数据卷、网络等。新版本Docker已经把Compose集成进docker子命令,直接写 docker compose,不用再单独装docker-compose Python版。装完Docker就有这个能力,所以它已经成为我个人最常用的部署方式。
7.2 MySQL 8.0实例化配置
新建一个目录,在里面放docker-compose.yml:
yaml复制services:
mysql8:
image: mysql:8.0
container_name: mysql8
restart: always
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: root123456
MYSQL_DATABASE: appdb
volumes:
- mysql8_data:/var/lib/mysql
volumes:
mysql8_data:
然后在同目录执行:
bash复制docker compose up -d
docker compose ps
docker exec -it mysql8 mysql -uroot -proot123456
这里解释几个关键参数。restart: always表示容器异常退出后自动拉起;MYSQL_ROOT_PASSWORD和MYSQL_DATABASE是MySQL镜像官方支持的环境变量,容器首次启动时会自动完成初始化;mysql8_data是命名卷,由Compose自动创建,数据持久化在卷里而不是容器可写层。
一个实际经验:MySQL 8.0默认的认证插件是caching_sha2_password,老的一些客户端工具和旧版程序可能连不上。如果遇到认证失败,可以给MySQL加启动参数指定mysql_native_password,但MySQL 8.4已经移除了这个插件,更推荐的方式是升级客户端。另外,生产环境一定不要用根密码直连,至少要单独创建业务账号并限制权限。
7.3 Redis主从架构编排
Redis主从是常见的高可用基础形态。在同一个Compose文件里定义两个服务:
yaml复制services:
redis-master:
image: redis:7
container_name: redis-master
restart: always
ports:
- "6379:6379"
command: ["redis-server", "--appendonly", "yes"]
redis-slave:
image: redis:7
container_name: redis-slave
restart: always
depends_on:
- redis-master
ports:
- "6380:6379"
command: ["redis-server", "--replicaof", "redis-master", "6379"]
执行:
bash复制docker compose up -d
docker exec -it redis-slave redis-cli INFO replication
INFO replication的输出里,如果看到role:slave和master_link_status:up,说明主从已经建立。这里的关键点有两个:一是Compose创建的默认网络里,服务名就是容器的主机名,所以redis-slave能通过“redis-master”这个域名访问到主节点;二是depends_on保证了启动顺序,先启动主节点再启动从节点。
这个配置只够演示和测试,生产环境的Redis主从还需要考虑密码认证、持久化策略、监控告警等,不建议直接拿这套配置上生产。但作为理解Compose和容器网络的教学案例,它非常典型。
8. 常见安装与启动报错排查
8.1 virtualization support not detected
这是Windows用户装Docker Desktop时最常撞到的报错之一。Docker Desktop运行需要虚拟化支持,如果检测不到就拒绝启动。先打开任务管理器,切到“性能”选项卡,点CPU,看“虚拟化”这一项是否显示“已启用”。如果显示“已禁用”,需要进BIOS开启Intel VT-x或AMD-V,不同主板品牌入口不一样,一般是开机按Del或F2。
如果任务管理器显示“已启用”,但Docker还是报virtualization support not detected,通常是Windows的虚拟机平台功能没开。管理员身份运行PowerShell,执行:
powershell复制Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All
或者去“控制面板-程序和功能-启用或关闭Windows功能”里勾选Hyper-V和虚拟机平台,重启后应该就好了。这里注意:如果你同时安装了其他虚拟化软件,或者系统开启了内核隔离、基于虚拟化的安全,有时也会干扰Docker Desktop的虚拟化检测,可以先关闭再排查。
8.2 docker desktop failed to start
报错信息很泛,但原因通常集中在这几类。第一,WSL2内核太旧,用 wsl --update 更新内核后重启。第二,Docker Desktop服务文件损坏,可以完全退出托盘图标,再以管理员身份重新启动。第三,磁盘空间不足,Docker引擎启动需要几百MB到几GB的临时空间,尤其在你配置了较大数据卷后,磁盘满了引擎会直接拒绝启动。第四,Windows更新后出现的老毛病,系统更新会重置一些虚拟化相关组件,导致Docker Desktop处于半死状态。
排查思路是从浅到深:先重启Desktop,再看WSL版本,再查磁盘,最后实在不行用Desktop自带的Troubleshoot或重置。没有更快的捷径,但大多数“failed to start”在 wsl --shutdown 然后重启Desktop之后都能解决。这也是我用的次数最多的一个操作。
8.3 无法连接Docker API
Windows上常见的报错长这样:failed to connect to the docker api at npipe:////./pipe/dockerdesktoplinuxen。本质是客户端连接不到Docker引擎,原因几乎都是引擎还没起来或者已经崩了。遇到这条报错,我的建议是先不要重复执行docker命令,先去托盘看Docker Desktop的状态,等引擎图标稳定了再试。
还有一种情况是刚装完Desktop,第一次启动还没完成初始化,用户就急着敲命令,此时引擎的管道还没有建立,自然会报连接失败。Linux上对应的报错是Cannot connect to the Docker daemon at unix:///var/run/docker.sock,那要么守护进程没启动,执行systemctl start docker,要么是权限不够,去确认docker组配置。这类问题本质都是“服务端没就绪”,不是命令本身的问题。
8.4 权限错误与网络不通
Linux上最常见的权限错误是:Got permission denied while trying to connect to the Docker daemon socket。原因是当前用户不在docker组里。一条命令解决:
bash复制sudo usermod -aG docker $USER
重新登录后生效。如果不想重新登录,可以用 newgrp docker 在当前终端临时激活。
容器内网络不通是另一个高频问题。典型表现是容器能启动,但容器内部ping不通外网,或者apt/pip下载超时。先检查能否ping通宿主机网关,再看DNS配置。最简单粗暴但有效的方案是在daemon.json里加DNS:
json复制{
"dns": ["223.5.5.5", "8.8.8.8"]
}
重启Docker后再试。生产环境还要检查防火墙、安全组,是否放行了容器需要访问的目标端口,这个容易忽略。我排查过一台云服务器上的容器访问数据库超时,最后发现是安全组把3306端口限制了,和Docker本身没关系。
9. 装Docker这些年,我的几点实践建议
装过的Docker环境应该超过几十台了,从个人笔记本到云服务器都有,这里分享几条总结出来的习惯。第一条,装完立刻验证,不要装完就不管了。docker run hello-world虽然简单,但这一条命令能把引擎、网络、镜像链路都验证到位,等于给整个安装流程画了一个句号。
第二条,镜像加速一定要配。不管你的网络环境现在多顺,配置加速器花三分钟,换来的是以后每次拉镜像都少一分等待。而且一旦你开始用Compose部署组件,拉镜像的次数会指数级增加,加速器的价值也会越来越明显。
第三条,生产环境少用latest,多用明确版本tag。latest镜像在你不知道的时候就会变成新版本,服务重启后行为可能完全变了。docker pull nginx:1.25这种写法看着麻烦,但能让环境可复现、可回滚,这才是Docker带来的确定性。另外,新手经常被“镜像删不掉”误导,其实多半是忘了还有个容器在用这个镜像,docker ps -a一查就清楚了。
最后再说一个踩过坑的细节:Docker的数据卷不要轻易删,它不在容器的生命周期里,而且命名卷在Docker内部有独立的管理空间。我早期经常做“清理”操作,清理完了发现数据库数据也没了。现在我的习惯是:容器随便删,volume删前先确认里面有没有值得保留的数据。
“如何装docker”这个问题看似基础,但真正把它用顺手,需要的不只是安装命令,还有对镜像、容器、卷、网络这几个概念的理解。希望这篇内容能帮你少走一点弯路,把更多时间花在真正想做的事上。
