资讯动态

Ubuntu从零安装Docker全攻略:避坑指南与MySQL/Redis容器部署

发布时间:2026/9/16 10:15:02 来源:尧图企业网站定制
刚帮朋友从零把一台Ubuntu 22.04装到Docker能正常跑MySQL和Redis前后折腾了近两个小时踩了权限、源、镜像拉取超时好几个坑。回来把整个过程整理成这篇沉淀希望帮你绕开我走过的弯路。这篇内容适合所有想在Ubuntu上安装Docker的同学参考不管是服务器、虚拟机还是WSL2里的Ubuntu环境套路基本一致。我会从为什么不用apt install docker.io讲起到逐步安装Docker Engine、配置镜像加速、部署第一个容器最后附上高频问题排查清单。确保你看完能独立搞定安装也能知道出了问题去哪里看日志、怎么定位。1. 装之前先想清楚的三件事1.1 你的Ubuntu版本和内核是否达标Docker对Linux内核有要求最低是3.10版本但实际生产中我会建议直接用内核4.0以上。Ubuntu 20.04 LTS默认内核是5.4Ubuntu 22.04 LTS是5.15Ubuntu 24.04 LTS是6.8这几个版本装上Docker都没问题。如果你还在用Ubuntu 16.04或者更老的版本建议先升级系统因为老版本的内核和systemd都可能存在兼容性问题。检查内核版本很简单一条命令uname -r另外如果你是在虚拟机里装Ubuntu比如VMware或VirtualBox记得开启CPU的虚拟化功能VT-x/AMD-V。不开启的话Docker本身还能跑但如果你后续想用Docker Desktop或者跑KVM类的虚拟化应用就会直接报错。这个点我要重点提一下因为“virtualization support not detected”这个报错是高频问题后面专门讲。1.2 选Docker Engine还是Docker Desktop很多新手上来就想装Docker Desktop因为它有图形界面看起来友好。但我要说句实话在Ubuntu服务器上我们绝大多数场景只需要Docker Engine也就是命令行版本。Docker Desktop是为桌面开发场景设计的它内部会起虚拟机占内存更多而且在Ubuntu上还要求必须开启KVM虚拟化环境要求更苛刻。我常用的选择方式是这样场景推荐方案服务器/虚拟机部署Docker Engine docker compose本地Ubuntu桌面开发Docker Engine 即可想用图形界面可以考虑 Portainer想用完整Docker Desktop优先Windows WSL2Ubuntu桌面场景反而不推荐Docker Engine和Docker Desktop的核心容器运行时是同一个命令也完全一样所以不存在“装了Engine就低人一等”的说法。反而Engine更轻量、更稳定、更贴近生产环境排错也更简单。1.3 不要直接用apt install docker.io这是新手最容易踩的第一个坑。Ubuntu的官方软件源里确实有docker.io这个包直接装确实方便但它有几个问题版本更新滞后严重可能落后官方大半年默认没有自动补全、日志清理插件等周边工具后续你想用官方源升级还得先卸掉这个包迁移麻烦。正确的做法是从Docker官方仓库安装这样你能拿到最新稳定版后续apt upgrade也能直接更新切源路径顺畅。官方仓库的地址虽然在国内有时不稳但配置镜像源之后基本没有问题这个在第三节我会给出具体方案。2. 官方仓库方式安装Docker Engine2.1 先清理环境如果系统之前装过Docker相关的包先用下面的命令把这些删干净避免残留配置干扰后续安装sudo apt remove docker docker-engine docker.io containerd runc这一步不必须每次都执行但如果你不确定系统之前是否装过建议跑一遍。不执行也没关系官方安装脚本会自己处理冲突。真正需要留神的是/var/lib/docker目录这是Docker默认的数据目录里面存放了所有镜像、容器和卷。如果之前的数据还要用先备份再操作否则卸载后数据不会自动清掉但重装后可能会因为版本不同导致数据不兼容。2.2 安装依赖和添加官方GPG密钥执行下面的命令安装必要的软件包sudo apt update sudo apt install -y ca-certificates curl然后创建密钥管理目录并导入Docker官方的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这里有个小细节install -m 0755 -d是创建目录并设置权限比mkdir -p多做了权限管理这一件事。Docker官方安装文档现在推荐的做法就是先建目录再放keyring文件再设置644权限。如果你少了chmod ar这一步后面apt update会报错说keyring不可读这是我在实际运维中见过特别多次的问题。2.3 把Docker官方源写入apt源列表这一步要区分架构。我在Ubuntu x86_64上用的是amd64树莓派等ARM设备用arm64。用dpkg --print-architecture看一下dpkg --print-architecture然后添加源。我把命令写在下面这是Ubuntu 22.04/24.04通用的写法echo deb [arch$(dpkg --print-architecture) signed-by/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release echo ${UBUNTU_CODENAME:-$VERSION_CODENAME}) stable | sudo tee /etc/apt/sources.list.d/docker.list /dev/null这里$(. /etc/os-release echo ${UBUNTU_CODENAME:-$VERSION_CODENAME})是动态获取系统版本的代号比如Ubuntu 22.04会解析出jammy24.04会解析出noble。好处是你换了系统版本这段命令不用改。如果解析失败也可以手动写死deb [archamd64 signed-by/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu jammy stable。添加完源之后再执行一次sudo apt update让系统识别新源。如果这一步网络超时那就到了该配置镜像源的时候了不急第三节专门解决这个问题。2.4 安装Docker Engine和配套工具现在可以正式安装了sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin解释一下这些包各自是干什么的docker-ceDocker社区版引擎主程序就是真正干活的守护进程。docker-ce-cli客户端命令行工具就是我们敲的docker命令。containerd.io容器运行时负责实际创建和管理容器生命周期。docker-buildx-plugin用于构建多架构镜像的插件默认会装上。docker-compose-pluginDocker Compose v2插件后面编排MySQL、Redis的时候要用。安装完成后启动并设置开机自启sudo systemctl enable docker sudo systemctl start docker用systemctl status docker看一眼运行状态看到active (running)就说明守护进程起来了。这里多说一句很多教程让你装完直接跑docker version这是不对的docker version只能验证客户端和服务端能否对接如果服务端没起它会只显示客户端信息容易让人误判。先看服务状态更靠谱。2.5 把当前用户加进docker组这一步是很多教程会忽略但实际极其重要的一步。默认情况下只有root用户和docker组的成员才能访问Docker守护进程。你不加组就得每次都敲sudo docker非常痛苦。加到docker组sudo usermod -aG docker $USER然后重新登录或者执行下面的命令让组变更立即生效newgrp docker验证一下docker run hello-world这条命令会先从Docker Hub拉取hello-world镜像很小大约几KB然后在容器里运行它最后输出一段说明文字。如果你看到Hello from Docker!说明整个安装已经成功了。这也是个人尽皆知的验证方式但我建议你留意一下这段输出里面“容器在完成工作后就退出了”这个概念这对理解容器的生命周期很有帮助。3. 配置镜像加速解决拉取超时3.1 为什么需要配置加速Docker默认的镜像仓库是Docker Hub架设在国外。从国内网络直接拉取大型镜像比如MySQL、Redis、Ubuntu基础镜像经常出现进度条卡住不动或者等半天提示net/http: TLS handshake timeout。最难受的是这类超时错误是间歇性的有时候重试能成有时候连续失败非常浪费耐心。解决方法就是在Docker守护进程配置里加入国内公共镜像源。注意这不是什么黑科技就是把镜像拉取的访问路径指向国内的速度更快的镜像仓库。Docker官方本身也支持配置多个镜像源拉取同一个镜像时如果第一个源失败会自动切换下一个。3.2 修改daemon.json配置文件你需要创建或修改/etc/docker/daemon.jsonsudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json -EOF { registry-mirrors: [ https://docker.m.daocloud.io, https://dockerproxy.com, https://docker.mirrors.ustc.edu.cn ] } EOF上面这几个源是我实际用下来相对稳定的。其中docker.m.daocloud.io是DaoCloud提供的公共镜像加速覆盖范围广中科大源是老牌教育网源稳定性好。不同地区、不同运营商网络表现会有差异建议保留两到三个做备选。改完配置后重启Docker服务sudo systemctl daemon-reload sudo systemctl restart docker重启完之后可以用docker info查看配置是否生效docker info | grep -A 5 Registry Mirrors如果输出列表里能看到你配置的几个地址说明加速已经生效。3.3 配置完加速还慢怎么办有时候配置了镜像加速拉取仍然很慢这时候问题往往出在“镜像源没有对应的镜像”上。比如一些很偏门的第三方镜像国内源根本没同步Docker会退回到Docker Hub原始地址拉取慢就是正常的。另外有些镜像在Docker Hub上本身多层合并后的体积很大比如node:20完整版、python:3.12这种开发镜像实际下载接近1GB再快的源也要花时间。如果项目场景允许优先选alpine版本的基础镜像体积能小一个数量级这在后面的MySQL、Nginx部署里我会演示。最后说一个老实但有效的土办法如果你用的是国内云服务器比如阿里云、腾讯云它们的控制台里都有专属镜像加速地址一步到位速度比公共源还快。很多人买了云服务器却在网上搜索公共加速源根本没意识到自己的云厂商就送了加速服务。4. 部署第一个容器Nginx和MySQL4.1 用docker run跑一个NginxDocker装好光看hello-world肯定不够过瘾我们用Nginx来体验一下完整的容器部署流程。拉取镜像并运行docker run -d --name web-test -p 8080:80 nginx:alpine我拆开解释一下这几个参数-d后台运行容器让出终端。--name web-test给容器起一个名字方便后续管理。-p 8080:80端口映射把宿主机8080端口转发到容器的80端口。nginx:alpine基于Alpine Linux精简版的Nginx镜像体积小资源占用少。执行完之后访问http://你的服务器IP:8080就能看到Nginx默认欢迎页。如果打不开第一件事检查防火墙是否放行了8080端口第二件事用docker ps -a看容器是否在运行第三件事看容器日志。查看容器日志的命令docker logs web-test如果你看到类似bind() to 0.0.0.0:80 failed (13: Permission denied)的报错那是因为容器内进程没有权限绑定80端口解决办法是更换映射端口或者用root用户运行容器。这个在实际生产中遇到不少。4.2 部署MySQL 8理解数据卷接下来部署一个更贴近业务场景的MySQL 8.0。你直接在热词里能看到“docker安装mysql8.0并使用”排在很前面说明这是大家真正关心的需求。先拉镜像docker pull mysql:8.0然后运行docker run -d \ --name mysql8 \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORDyourpassword \ -e MYSQL_DATABASEtestdb \ -v /opt/mysql-data:/var/lib/mysql \ mysql:8.0这里重点讲两条参数第一-e是环境变量。MySQL镜像启动时会读取这些变量来初始化数据库。MYSQL_ROOT_PASSWORD设置root密码MYSQL_DATABASE会额外创建一个数据库。如果你不设置密码相关变量容器会因为安全机制直接启动失败。第二-v /opt/mysql-data:/var/lib/mysql是数据卷挂载。它的意思是把宿主机/opt/mysql-data目录映射到容器内MySQL的数据目录。容器删了、重建了只要这个目录还在数据就还在。这个习惯一定要养成否则哪天不小心删了容器数据库文件跟着一起没了那种教训一次就够痛。映射完了还需要注意目录权限问题。MySQL容器内有自己的运行用户mysql它需要能读写挂载目录。如果你在宿主机上创建的目录权限过严比如直接用root创建且权限是700容器内用户写入就会报Permission denied。解决办法是先创建目录并授权mkdir -p /opt/mysql-data chown -R 1000:1000 /opt/mysql-data1000:1000是MySQL官方镜像中mysql用户的UID:GID。不同镜像的用户ID可能不一样这个要留意。4.3 容器生命周期管理四件套跑起来之后日常维护主要就四个命令查看容器列表docker ps docker ps -a # 包含已停止的停止、启动、重启、删除docker stop mysql8 docker start mysql8 docker restart mysql8 docker rm mysql8 # 删除前要先stop进入容器内部docker exec -it mysql8 bash在容器内敲mysql -uroot -p就能连上数据库这对排查数据库问题是必备操作。进入容器后容器本质是一个精简版Linux环境很多命令可能没有安装比如vim默认没有这是正常的不用慌。5. 常见安装与运行问题排查清单5.1Got permission denied while trying to connect这个报错是权限问题最常见的表现。你执行docker ps的时候提示这个说明Docker守护进程正常工作但你的用户没有权限连接它。确认一下groups $USER如果你的用户名没有出现在docker组里就回头执行第2.5小节的用户组配置。如果已经加入了docker组但还是报这个错那很可能是因为当前shell会话还是旧的用户身份执行newgrp docker或者重新登录一次就好。5.2Cannot connect to the Docker daemon这个报错含义是客户端找不到Docker守护进程。先确认服务是否在运行sudo systemctl status docker如果服务是inactive (dead)直接启动sudo systemctl start docker如果服务启动失败查看详细错误sudo journalctl -u docker.service --no-pager -n 50我遇到过一个比较隐蔽的情况Docker和本机防火墙iptables规则冲突导致服务起不来。这种时候看日志会发现Failed to start Docker Application Container Engine后面跟着iptables相关错误。临时解法是把/etc/docker/daemon.json里加上iptables: false但这个操作会影响容器网络隔离我不推荐长期使用最好还是排查具体是哪个防火墙规则冲突了。5.3 端口冲突如果你启动容器时报Bind for 0.0.0.0:8080 failed: port is already allocated说明宿主机上8080端口已经被占了。查一下是谁占了sudo lsof -i:8080 # 或者 sudo ss -tlnp | grep 8080处理方式有两个杀掉占用进程或者改容器映射端口。我建议优先改端口因为杀进程有风险你不一定知道那个进程是干什么的。比如在同一台机器上还要跑另一个Nginx你就可以把容器的映射改成8081:80。还有一种情况是MySQL的3306端口被本机已有的MySQL服务占用。如果你是为了开发环境用Docker起MySQL建议先把宿主机自带的MySQL服务停掉或者直接改Docker映射端口为3307:3306避免冲突。5.4 老版本Ubuntu装不上Docker如果你还在用Ubuntu 18.04会发现添加Docker官方源后apt update可能报错找不到Release文件。原因是Docker官方已经停止对18.04及以下版本的仓库更新了你要么装旧版Docker要么老实升级系统。我个人建议是升级系统别在旧版本上浪费时间。Docker对内核版本有硬性要求旧的发行版内核太老某些新特性用不上运行时稳定性也差。从投入产出比看花两小时升级系统比重装十次旧版Docker值得多。5.5Virtualization support not detected怎么处理这个报错在热词里出现频率很高虽然它更多出现在Docker Desktop上但如果你在WSL2里的Ubuntu上使用Docker也可能撞上。先检查虚拟化是否开启grep -E --color (vmx|svm) /proc/cpuinfo如果没输出说明CPU虚拟化没有开启或者当前环境不支持嵌套虚拟化。解决办法物理机重启进BIOS/UEFI找到Intel Virtualization Technology或AMD SVM Mode设置为Enabled。VMware虚拟机关掉虚拟机在VMware设置里勾选“虚拟化Intel VT-x/EPT”或“虚拟化AMD-V/RVI”。VirtualBox虚拟机设置里找到“启用VT-x/AMD-V嵌套分页”并勾选。云服务器本身不支持嵌套虚拟化但云服务器上的Ubuntu通常不需要Docker Desktop直接用Docker Engine即可完全不依赖这个特性。所以我的观点是如果你是服务器上跑Docker看到这个报错不用慌你根本不需要管虚拟化支持直接用Engine就好如果你是本地桌面环境用Docker Desktop那就老老实实去BIOS打开虚拟化。5.6 排查问题前三步始终不变无论遇到什么Docker问题我都推荐从三个方向切入看服务状态、看容器状态、看日志。第一步确认Docker服务在跑systemctl status docker。 第二步确认容器在跑docker ps -a尤其注意STATUS列是Up还是Exited。 第三步看日志运行中的容器用docker logs 容器名异常退出的容器同样可以用这个命令查看原因。日志永远是最直接的线索别靠猜。几次找不到原因基本都是因为懒得看日志凭感觉在那里试错浪费时间。6. 进阶用Docker Compose管理多容器环境6.1 Docker Compose解决什么问题到这一步你已经能单容器跑了。但实际开发中一个项目往往需要MySQL、Redis、Nginx多个容器协作每次都手动敲docker run不仅长还容易记错参数。Docker Compose的作用就是把这些容器的启动参数统一写在一个docker-compose.yml文件里一条命令全部启动。它的好处有两个第一配置可视化所有人通过一个文件就能看懂整个项目的依赖关系第二可复制性强新同事拉到代码一条docker compose up -d就能把整个环境拉起来。之前有朋友问过我“我有构建好的镜像只是想在别的机器上跑起来还需要Compose吗”如果只是单容器没有依赖关系直接docker run就够了。但如果涉及多容器、网络互通、数据卷共享Compose的优势就体现出来了。6.2 写一个Compose文件部署MySQL和Redis在项目目录下创建docker-compose.ymlversion: 3.8 services: mysql: image: mysql:8.0 container_name: dev-mysql restart: always ports: - 3306:3306 environment: MYSQL_ROOT_PASSWORD: root123456 MYSQL_DATABASE: demo volumes: - ./mysql-data:/var/lib/mysql networks: - dev-net redis: image: redis:7-alpine container_name: dev-redis restart: always ports: - 6379:6379 volumes: - ./redis-data:/data command: redis-server --appendonly yes networks: - dev-net networks: dev-net: driver: bridge说明几个关键点restart: always容器异常退出后自动重启适合长期运行的服务。volumes里的./mysql-data是相对路径会在当前目录下创建数据目录方便整个项目目录一起迁移。command覆盖镜像默认启动命令Redis这里开启AOF持久化。networks让MySQL和Redis在同一个自定义网络中后续微服务连接直接用容器名dev-mysql、dev-redis就能解析到IP不需要网卡地址。启动docker compose up -d查看状态docker compose ps停止docker compose down如果你还要加一个Redis主从可以在services下再加一个redis-slave节点配置里加上--slaveof dev-redis 6379一条命令一起启动。热词里“docker安装redis主从”就是这么玩的加两个service、两行配置而已。6.3 IDEA里怎么用Docker镜像现在开发流程里还有个高频场景叫“IDEA打包Docker镜像”。本质上就是把项目代码打进一个包含Java运行环境的镜像里让容器可以直接启动项目。传统开发流程本地把Java项目打成Jar包。在服务器上装JDK、配环境变量。把Jar包上传到服务器手动启动。Docker化之后项目根目录写一个Dockerfile内容类似这样FROM openjdk:17-jdk-alpine VOLUME /tmp COPY target/demo.jar app.jar ENTRYPOINT [java,-jar,/app.jar]执行构建docker build -t demo-app:latest .运行docker run -d -p 8080:8080 demo-app:latestIDEA本身也集成Docker插件装了docker插件之后可以直接在Services面板看到本地Docker实例右键Dockerfile选Build Image就能打包不需要切换到命令行。这里我再强调一个开发小技巧如果你的镜像在IDEA里构建特别慢先看看是不是在拉基础镜像。openjdk:17-jdk-alpine这种镜像全量拉取可能要好几分钟但只要你本地已经拉过一次后续构建都是秒级。7. 最后再分享一个日常维护技巧装好Docker之后日常维护中最重要的习惯之一就是定期清理无用镜像和容器。开发调试几天后本机经常堆积一大堆none标签的悬空镜像占用的磁盘空间可能有好几个G。清理命令docker system prune这条命令会把所有停止的容器、悬空镜像、未使用的网络都删掉。如果想连没被引用的镜像一起清理加个-a参数docker system prune -a注意这条命令会清理所有未被运行中容器引用的镜像如果你本机保存了一些不常用的自定义镜像建议先确认哪些还需要。我自己的习惯是每周跑一次docker system df看看磁盘占用情况做到心中有数。另外如果你经常改容器配置记得“容器重启不等于配置生效”。Docker容器是不变的docker restart只是重启了进程不会重新读取docker run时的参数。如果改了端口映射、环境变量、挂载目录正确做法是删掉旧容器、用新参数重新docker run或者用Compose文件改完重新docker compose up -d。这算是很多人容易搞混的地方记住这一点能省去不少排查时间。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价