Docker入门实战:镜像容器与常用命令全解析

Docker入门实战:镜像容器与常用命令全解析 先问一个问题你在自己的电脑上装过软件、配过环境吗装过MySQL、Redis或者某个Java项目折腾了半天最后因为一个版本号对不上、一个依赖缺失整个环境直接崩掉Docker就是专门解决这个问题的。它把应用连同它需要的运行环境一起打包装到哪儿都能直接跑。这篇文章作为Docker入门系列的第一篇不谈高深原理用最直白的方式把Docker是什么、能干嘛、怎么装、怎么用一次讲清楚。新手照着做就能跑起来老手也可以当速查手册看看。1. 内容整体设计与思路拆解1.1 到底怎么理解Docker集装箱思维很多人第一次接触Docker容易把它理解成“轻量级虚拟机”这个说法没错但容易带偏。虚拟机是把整台电脑模拟出来里面要装一个完整的操作系统Docker不像VM那样它不模拟整个操作系统而是直接共享宿主机的内核在上面划分出一个个独立空间来跑应用。打个比方虚拟机是你要出差直接租了一整套房子Docker是你要出差只订了一个标准化集装箱把需要的行李放进去到哪儿都能直接拎包入住。集装箱的好处是什么标准化、隔离、搬运方便。Docker的核心思想就是这三件事。这个“集装箱”在Docker里叫做容器Container而集装箱的“设计图”叫做镜像Image。镜像保证了在不同机器上构建出来的环境完全一致容器则是这个环境运行起来的实例。理解这两者的关系是入门的第一道坎镜像不是装好的系统而是“安装包 运行环境 配置”的模板容器是模板运行起来后生成的一个独立进程。你可以从同一个镜像启动成千上万个容器每个容器都是独立的互不影响。1.2 Docker能解决什么现实问题Docker最大的价值我认为就三点消除环境差异、简化部署、资源隔离。先说环境差异。你有没有遇到过这种情况代码在你自己电脑上跑得好好的同事拉下来却启动不了老板让你查明原因最后发现是JDK版本不一致、依赖冲突、端口被占。有了Docker你就可以在镜像里把这些问题一次性固定下来别人拿到直接运行环境问题就消失了。再说部署流程。没Docker的时候部署一个MySQL要装软件、初始化数据、配置权限、设置开机自启步骤繁琐且每台机器都可能踩不同的坑。有了Docker后一条命令就能完成部署而且反复执行的部署结果完全一致。这对运维来讲是翻天覆地的变化——部署从“工程项目”变成了“搬运货物”。最后是资源隔离。不同应用可以跑在不同的容器里某个容器崩溃或者占用过高不会拖垮其他容器和宿主机。1.3 为什么先用基础理论打底市面上很多教程上来就让你敲命令敲完虽然能跑起来但是出问题就懵了。这就是为什么第一部分要先讲清楚Docker的架构和核心概念镜像、容器、仓库、守护进程。理解这些概念之后后面再学安装和命令你会发现自己看报错都能看出病因来而不是瞎猜。2. 核心细节解析与实操要点2.1 Docker的三大核心概念镜像、容器、仓库这三个概念是所有Docker操作的基础必须先吃透。镜像Image是只读模板。你可以把它理解成Java里的类定义了对象的所有属性和行为但它本身不是一个运行中的东西。镜像是一个分层结构的文件每一层代表一条构建指令比如安装了什么软件、做了什么配置。这种分层设计是Docker能高效分发和存储的关键。容器Container是镜像的运行实例。前面说过一个镜像可以创建多个容器每个容器有自己独立的文件系统、网络和进程空间。容器在运行时会有一个可写层你往里写的数据都在这一层容器删了这层数据也没了。这是新手最容易踩的坑容器一删里面的数据全部消失没有备份机制。仓库Registry是存放镜像的地方类似于GitHub。从仓库拉取镜像的命令是docker pull推送的命令是docker push。默认的仓库是Docker Hub里面有大量的官方镜像和社区镜像。三者的关系用一句话说从仓库拉镜像用镜像创建容器在容器里跑应用。2.2 Docker引擎Client-Server架构Docker采用典型的Client-Server架构。你平时敲的docker命令是客户端Client真正干活的是一后台守护进程daemon。客户端收到你的指令后通过本地socket或HTTP接口把请求发给守护进程守护进程再去操作镜像、容器等资源。这个架构有一个实际好处客户端和守护进程不一定要在同一台机器上。你可以用自己的电脑远程控制一台服务器上安装的Docker。入门阶段了解即可但搞清楚这一点对后面排查问题很有帮助——很多报错的本质是“客户端连不上守护进程”而不是“命令敲错了”。2.3 Docker与虚拟机的本质区别很多人会问既然都是隔离干嘛不用虚拟机还要学Docker区别主要在三方面一是资源利用率。虚拟机需要完整的操作系统开机占几个G内存很正常Docker直接共享宿主机内核一个容器占用的资源可能只有几十兆。二是启动速度。虚拟机动辄几十秒甚至几分钟Docker容器通常是秒级甚至毫秒级启动。三是迁移和分发。虚拟机镜像是几个G的大文件而Docker镜像往往只有几百兆分层的设计还能让多个镜像共享同一层进一步节省存储和带宽。Docker的局限也要心里有数因为它共享宿主机内核所以不能运行和宿主机操作系统内核不同的软件。比如在Linux docker上跑Windows程序是不可能的反过来也一样。这是Docker在设计上有意为之的取舍换来的是极致的轻量。3. 实操过程与核心环节实现3.1 安装DockerWindows、macOS、Linux三条路线安装Docker是入门的第一道关卡也是很多新手第一次放弃的地方。分开说。Windows环境Win10/11 专业版、企业版、教育版用户推荐直接安装 Docker Desktop。安装包从官网下载双击运行一路下一步就行。但Install之前要先检查两件事一是系统虚拟化是否开启。打开任务管理器切到“性能”标签页看右下角的“虚拟化”是不是“已启用”。如果没有启用需要进BIOS把Intel VT-x或AMD-V打开否则Docker Desktop会报错提示virtualization support not detected。二是WSL 2是否装上。新版Docker Desktop依赖WSL 2作为后端来运行Linux容器如果之前没装过WSL安装完Docker Desktop后按提示执行命令wsl --install然后重启电脑。Windows家庭版也不需要慌同样可以装Docker Desktop不过需要手动启用“Hyper-V”相关的几个Windows功能。做法是控制面板 - 程序和功能 - 启用或关闭Windows功能勾选“虚拟机平台”和“适用于Linux的Windows子系统”重启后继续装。macOS环境macOS用户比较省心直接下载Docker Desktop for Mac拖到Applications里就行。注意区分Apple SiliconM1/M2/M3和Intel芯片的安装包两者架构不同选错误会出现在启动阶段的各种奇怪问题。Linux 环境以Ubuntu/Debian为例最稳妥的方式是通过官方apt源安装而不是下载deb包这样后续升级维护都更方便。安装命令如下# 更新索引 sudo apt-get update # 安装依赖包 sudo apt-get install -y ca-certificates curl gnupg # 添加Docker官方GPG密钥 sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg sudo chmod ar /etc/apt/keyrings/docker.gpg # 设置仓库 echo \ deb [arch$(dpkg --print-architecture) signed-by/etc/apt/keyrings/docker.gpg] 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-get update sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin装完之后执行systemctl start docker启动服务再执行docker --version确认安装成功。CentOS/RedHat系列区别不大把仓库地址从ubuntu换成centos即可依赖包管理工具从apt换成yum。注意Linux下安装Docker后直接执行docker命令会提示权限错误。原因是你当前用户不在docker用户组里。正确的做法是sudo usermod -aG docker $USER然后退出重新登录终端。不推荐用sudo直接跑所有docker命令后续自动化脚本会非常麻烦。3.2 Docker Desktop安装后的初始化配置Windows和macOS上装完Docker Desktop第一次启动会有一个比较耗时的过程。它会下载并初始化一个Linux虚拟机作为后端。启动完成后在Docker Desktop的设置中Settings有几个建议优先改掉的项目镜像加速Settings - Docker Engine在配置JSON的registry-mirrors字段里填入公共镜像加速地址。这个放后面专门讲。资源限制Settings - Resources调整可用的CPU、内存和Swap。如果是开发机建议给Docker分配至少4GB内存否则跑MySQL加Redis容易OOM。这里有个常规经验Docker Desktop默认的2GB内存能满足日常练习但要跑多个服务最好调到6GB以上。磁盘占用Docker镜像和容器数据会占用大量磁盘空间。建议把Disk image location改到一个空间充裕的盘避免C盘被撑满。换盘操作之前一直有人问Docker能不能安装到其他盘。Docker Desktop安装本身是装到C盘的但镜像数据目录可以挪。在Resources - Advanced里把Disk image location换到你想要的盘符即可实测可行。3.3 验证Docker安装成功装完之后用一个最简单的方式验证环境可用# 查看Docker版本 docker version # 查看Docker运行状态 docker info # 运行最经典的hello-world docker run hello-world输出一行Hello from Docker!就说明整个链路——客户端、守护进程、镜像拉取、容器运行——全部打通了。第一次跑hello-world会提示Unable to find image hello-world:latest locally然后自动开始拉取。这是因为本地没有这个镜像Docker自动执行了docker pull。如果能成功拉到说明你的网络可以和Docker Hub正常通信。4. 镜像加速不要再卡在“下载慢”上了4.1 为什么镜像下载这么慢国内开发者用Docker遇到的第一大痛点就是镜像拉取慢。为什么慢因为Docker Hub的服务器在海外连接不稳定且速度慢。几十MB的镜像可能等半天几GB的大镜像基本是灾难体验。这是网络基础设施的问题不是Docker本身的问题。所以解决方案不是去等而是配置镜像加速器——在拉取镜像时先连接到国内的服务节点由它代理转发并缓存速度会有明显提升。4.2 配置镜像加速的具体操作Linux环境下编辑或创建/etc/docker/daemon.json文件{ registry-mirrors: [ https://docker.1ms.run, https://docker.xuanyuan.me ] }配置完成后重启Docker服务sudo systemctl daemon-reload sudo systemctl restart docker重启后用docker info | grep -A 5 Registry Mirrors验证配置是否生效能看到自己填的地址就说明成功了。Windows和macOS下的Docker Desktop在Settings - Docker Engine的JSON文件里同样加上这段配置点击Apply Restart即可。注意不要同时配置太多的镜像加速源。实测下来保留一到三个速度最稳定的即可。多个源之间会自动进行故障切换配置过多反而可能因为等待超时拖慢拉取速度。配置加速器后原来需要等十分钟的大镜像通常几十秒就能拉下来。这是新手最容易忽略、但收益最高的一个配置步骤。5. Docker常用命令实战演练5.1 镜像操作拉取、查看、删除、清理# 拉取镜像 docker pull nginx:latest docker pull mysql:8.0 # 查看本地镜像 docker images # 搜索镜像不新增 docker search centos # 删除镜像 docker rmi nginx:latest # 删除所有悬空镜像none镜像 docker image prune关于tag标签问题多说一句nginx:latest和nginx:1.25是两个不同的镜像。latest标签不保证是最新版本它只是Docker默认填充的仓库标签。生产环境部署不要用latest一定要指定具体版本号否则某天基础镜像升级你重启容器实际跑的就是另一个版本了。5.2 容器操作运行、启动、停止、删除# 运行一个容器前台运行 docker run nginx # 运行一个容器后台运行最常用 docker run -d nginx # 给容器命名 docker run -d --name web-server nginx # 端口映射宿主机8080 - 容器80 docker run -d --name web-server -p 8080:80 nginx # 查看运行中的容器 docker ps # 查看所有容器包含已停止的 docker ps -a # 停止容器 docker stop web-server # 启动已停止的容器 docker start web-server # 重启容器 docker restart web-server # 删除容器必须先停止 docker rm web-server # 强制删除运行中的容器 docker rm -f web-server # 清理所有已停止的容器 docker container prune新手最常见的困惑是docker run和docker start的区别。run是“创建并启动一个新容器”如果本地没有对应镜像还会自动拉取start是“启动一个已经存在的容器”。很多人在容器停止后重复执行docker run结果创建了一堆同名的失败容器这就是概念没分清楚。5.3 进入容器和查看日志容器是隔离环境里面的应用跑得怎么样需要进容器内部或者看日志才能知道。# 进入容器的交互式终端 docker exec -it web-server /bin/bash # 查看容器日志实时输出 docker logs -f web-server # 只查看最近100行日志 docker logs --tail 100 web-server这个-it参数要记住-i表示保持标准输入打开-t表示分配一个伪终端。缺了这个参数进去之后没法敲命令或者看到的是乱码。有个使用上的建议调试用docker exec日常维护优先看日志。容器内部通常是最小化环境连vi、curl这些常用工具可能都没装想在里面排查问题会发现什么都干不了。而日志能看到应用输出的全部信息定位问题更快更准确。5.4 数据卷让数据不随容器消失前面说了容器删除后数据会跟着丢。解决这个问题的方法是数据卷Volume。# 将宿主机当前目录挂载到容器内的 /usr/share/nginx/html docker run -d --name web -v $(pwd)/html:/usr/share/nginx/html -p 8080:80 nginx # 使用具名数据卷 docker volume create mysql-data docker run -d --name mysql-server -v mysql-data:/var/lib/mysql mysql:8.0第一种方式是“绑定挂载”宿主机和容器共享目录适合开发调试——修改宿主机文件容器内立即生效第二种“具名卷”由Docker管理存储位置适合保存数据库等持久化数据。新手踩坑最多的地方是挂载路径写错。注意-v后面两个路径的顺序不能反冒号左边是宿主机路径右边是容器内路径。右边一定是容器内应用数据存放的真实路径写错会导致数据写到容器可写层里删容器又全没了。拿MySQL举例它的数据目录一定是/var/lib/mysql不是别的。6. 实战用Docker装一个MySQL 8.0理论学了那么多不过手都是虚的。下面用一个最常见的场景——用Docker部署MySQL 8.0——把前面的知识点全部串起来。这是很多网上教程的第一课也确实是性价比最高的练习项目。6.1 部署规划部署前先想清楚几件事数据放哪里用数据卷挂载到宿主机保证容器删了数据不丢配置放哪里把MySQL的配置目录也挂载出来方便改配置密码怎么设通过环境变量传入不用写死在命令里太多次端口怎么映射宿主机用3306还是其他端口避免和已装的本地MySQL冲突6.2 完整部署命令# 1. 准备本地挂载目录 mkdir -p /opt/mysql8/conf mkdir -p /opt/mysql8/data # 2. 编写基础配置 cat /opt/mysql8/conf/my.cnf EOF [mysqld] character-set-serverutf8mb4 collation-serverutf8mb4_unicode_ci default-time-zone08:00 EOF # 3. 启动MySQL容器 docker run -d \ --name mysql8 \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORDYourPassword123 \ -v /opt/mysql8/data:/var/lib/mysql \ -v /opt/mysql8/conf/my.cnf:/etc/mysql/conf.d/my.cnf \ --restart always \ mysql:8.0这里的参数逐个解释-d后台运行--name mysql8容器名方便后续管理-p 3306:3306宿主机3306端口映射到容器3306端口-e MYSQL_ROOT_PASSWORD设置root密码。注意这是初始化密码仅当数据目录为空时生效-v前后两个挂载分别是数据目录和配置文件--restart always容器意外退出时自动重启相当于开机自启6.3 验证并连接# 查看容器状态 docker ps | grep mysql8 # 查看初始化日志 docker logs -f mysql8 # 进入容器连接MySQL docker exec -it mysql8 mysql -uroot -p如果一切顺利会看到日志末尾出现ready for connections然后用密码就能登录MySQL。如果连接不上优先排查这几件事端口是否被占用ss -lntp | grep 3306防火墙是否放行ufw status测试环境可以直接关掉MySQL初始化是否完成日志没出现ready for connections之前连接会失败这是正常的等几十秒再连密码是否包含特殊字符如果密码里有$、!等特殊符号需要在命令行里转义或者用单引号包裹6.4 进入容器连接MySQL# 从容器内部进入MySQL docker exec -it mysql8 mysql -uroot -p # 从宿主机或客户端工具连接 mysql -h127.0.0.1 -P3306 -uroot -p注意容器内MySQL的socket文件路径是/var/run/mysqld/mysqld.sock本地客户端默认会找这个路径。如果用宿主机上的mysql客户端连接容器内的MySQL不能省略-h127.0.0.1否则会走本地socket连不上就报错。这里还有一个细节如果宿主机本来装过MySQL或者其他服务占用了3306端口可以换一个映射端口例如-p 3307:3306客户端连接时相应改成-P3307。这是Docker对比传统安装非常大的优势——端口冲突不用卸载谁换个映射就行。7. 常见问题与排查技巧实录7.1 Docker Desktop启动失败报错信息Virtualization support not detected这个是Windows上最常见的启动失败原因。处理路径重启进BIOS开启Intel VT-x或AMD-V控制面板 - 程序和功能 - 启用或关闭Windows功能勾选“虚拟机平台”执行bcdedit /set hypervisorlaunchtype auto管理员权限然后重启确认WSL 2已安装wsl --status报错信息Failed to connect to the Docker API at npipe:////./pipe/docker-desktop-linux-engine这个也是常见报错。通常不是Docker的问题而是WSL 2后端没启动成功。处理步骤# 在PowerShell管理员中重启WSL wsl --shutdown # 然后重新启动Docker Desktop如果还不行去Windows设置里检查WSL版本是不是1.xwsl -l -v如果是1.x升级到2wsl --set-version 2。7.2 Linux下docker服务无法启动systemctl status docker大概率是配置写错了最常见的是/etc/docker/daemon.json里的JSON语法错误。前端和运维经常写配置文件JSON里多一个逗号、少一个引号Docker服务直接起不来。排查方法执行dockerd --debug单独跑一下守护进程它会直接告诉你配置文件的哪一行有问题。修好配置文件再systemctl restart docker。7.3 容器启动了但访问不到这是个排查路径问题。按顺序查容器是否还在运行docker ps端口是否映射成功docker ps看PORTS列没有-说明映射没生效容器端口是否真的在监听docker exec -it 容器 bash然后curl 127.0.0.1:80如果容器内通、宿主机不通说明是端口映射或防火墙的问题防火墙systemctl status firewalld测试环境可以firewall-cmd --add-port8080/tcp --permanent firewall-cmd --reload7.4 磁盘被Docker占满镜像、容器日志、数据卷都会占磁盘空间。最常见的元凶是容器日志特别是在跑生产应用或者被反复重启的容器。排查命令# 查看磁盘占用排行 docker system df # 一次性清理所有不用的数据 docker system prune -a --volumes注意最后这条命令会删除所有未被容器使用的镜像和全部匿名数据卷慎用。日常可以只做两件事限制日志大小 清理临时残留。限制容器日志大小的方式是在daemon.json里加配置{ log-driver: json-file, log-opts: { max-size: 10m, max-file: 3 } }这组配置表示单个日志文件10MB最多保留3个。配置重启Docker后对所有新容器生效。7.5 镜像下载慢或者卡住这一步在Windows上出现过很多次特别在首次拉取大镜像时。如果配置完镜像加速仍然慢可以试试下面的顺序排查确认加速配置生效docker info | grep -i registry确认网络通畅ping一下镜像加速地址重启Docker让加速配置彻底加载换一个加速源如果是公司网络有防火墙或代理还需要额外配置Docker的代理。这个属高级操作基础阶段遇到比较少见了解到有这个问题就够了。8. 下一步从入门到熟练的关键路径这一篇把Docker的基础概念、安装、镜像加速、常用命令和MySQL部署实战都过了一遍。有了这些基础你已经可以自己折腾一些简单的容器了。我个人认为接下来最值得做的三件事是第一把这条docker run命令吃透。在命令行执行docker run --help从头到尾读一遍所有参数不理解的上网查。这条命令的参数涵盖了Docker最常用的80%功能读懂它Docker的基本功就有了。第二用Docker Compose把多个服务编排起来。比如用docker compose同时启动MySQL和Redis或者部署一个前后端分离的应用。Compose用YAML描述服务之间的关系是Docker从“单机工具”走向“编排平台”的分水岭。第三学习Dockerfile把你自己的应用打包成镜像。掌握了Dockerfile的编写你才算真正把Docker用起来了——能发布镜像意味着你不仅能“用”容器还能“造”容器。这个系列后续的文章里我会把Docker Compose、Dockerfile、数据卷持久化、网络模式这些内容挨个拆开讲。尤其是Docker Compose学会之后你会发现一键启动一套完整的开发环境真的就这么简单。最后分享一个我在实际使用中的小习惯每跑一个新容器先想好三件事——数据放哪里、端口映射到哪个、容器删掉后会不会有影响。想清楚这三点再敲命令能少踩80%的坑。