拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Debian 12安装Docker实战:部署MySQL、Redis与GitLab全流程

做后端和运维的人几乎都绕不过 Debian 和 Docker 这一对组合。Debian 适合当服务器底座Docker 适合把运行环境标准化两者配在一起基本是生产环境的默认起手式。这篇东西是我从零开始在一台 Debian 12 机器上安装 Docker、配置镜像加速、再把 MySQL、Redis 和 GitLab 都跑起来的全过程记录适合刚准备把服务容器化的新手也适合想快速找到踩坑答案的老手。网上关于 Debian 装 Docker 的教程很多但大多数只给几行命令遇到问题跳过去很多细节得自己一遍遍试。我这次把从系统准备、安装方式、加速器配置到真实业务容器部署、日常命令、报错排查全部串一遍每一步都解释为什么这么做。全程照着操作基本不会走弯路。1. 装 Docker 前先把 Debian 系统底子收拾好别急着敲安装命令。我见过很多人在一台 IP 随时会变、SSH 还会断的机器上装 Docker装完发现容器端口映射好了但服务地址找不到或者权限不对连不上最后卡在“怎么连服务器都连不上”这种问题上。所以第一步先把系统底子收拾利索。1.1 选 Debian 12 还是 Debian 11以及基础源调整如果手头没有特殊要求现在新装机器首选 Debian 12也就是 bookworm。它自带的内核版本比较新对 cgroup v2 和容器特性的支持更完整Docker 装上去基本不需要额外处理旧内核兼容问题。Debian 11 也能装但是后续在使用 compose、buildx 这些新功能时偶尔会遇到内核特性不全导致的怪问题。装完系统后第一件事是调整 apt 源。Debian 官方源在国内访问速度一般尤其在执行apt update或安装依赖时经常卡住。通常会改成阿里云或清华的镜像源。Debian 12 的源文件路径和老的 11 不太一样新格式放在/etc/apt/sources.list.d/debian.sources老格式在/etc/apt/sources.list。如果你看到的是 deb822 格式直接把 URIs 字段改成http://mirrors.aliyun.com/debian/即可老格式则把deb http://deb.debian.org/debian/整体替换成http://mirrors.aliyun.com/debian/再用 root 执行apt update apt upgrade -y另外桌面版 Debian 默认会开休眠和挂起。服务器不明显但如果你是拿台家用主机或者台式机装 Debian 来跑容器跑着跑着突然休眠断网会非常恼火。直接关掉systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target关完之后就算你按了电源键或者合盖机器也不会进入休眠容器服务就不会莫名其妙“失联”。1.2 固定 IP 和 SSH 免密登录先解决远程操作失联Debian 安装时如果用 DHCP 获取 IP重启后 IP 很容易变。Docker 起来之后你通过 IP 访问容器服务IP 一换就得满屋子找服务器。这个习惯我强烈建议先改掉用纯静态 IP 或者 DHCP 保留地址。如果系统里装了 NetworkManager可以直接用nmcli比编辑配置文件直观很多。先查网卡名ip a假设网卡叫eth0配置静态地址nmcli con mod eth0 ipv4.addresses 192.168.1.100/24 nmcli con mod eth0 ipv4.gateway 192.168.1.1 nmcli con mod eth0 ipv4.dns 223.5.5.5 nmcli con mod eth0 ipv4.method manual nmcli con up eth0如果你没装 NetworkManager用的是/etc/network/interfaces老方案改成这样auto eth0 iface eth0 inet static address 192.168.1.100 netmask 255.255.255.0 gateway 192.168.1.1改完执行systemctl restart networking或者直接重启机器验证。接着配 SSH 免密登录。很多人每次连服务器都要敲密码或者写脚本时卡在交互式密码输入上。解决办法是生成一对 SSH 密钥把公钥放到服务器上以后直接连不用输密码。在你自己电脑上执行ssh-keygen -t ed25519 -C your comment ssh-copy-id user192.168.1.100ssh-copy-id会提示输入一次服务器密码之后密钥就装好了。再测试ssh user192.168.1.100会发现直接登录不再问密码。这一步从根上解决了搜索里“如何自动输入密码”的问题。生产环境如果想更严格可以再把/etc/ssh/sshd_config里的PasswordAuthentication yes改成no彻底关闭密码登录只允许密钥登录。但这步一定要先确认密钥已经能正常登录否则容易把自己锁在门外。2. Debian 上安装 Docker 的三条路我推荐哪条Docker 在 Debian 上至少有三种装法官方 apt 源安装、Debian 自带源安装、二进制手动安装。我自己的选择是第一种原因后面会说。2.1 官方 apt 源安装最省心的路径Docker 官方为 Debian 维护了独立的软件仓库版本新更新及时docker compose、buildx这些周边组件也能一起装好。这是目前最推荐的方式。首先安装必要的依赖apt install -y apt-transport-https ca-certificates curl gnupg lsb-release然后导入 Docker 官方仓库的 GPG 密钥curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg再添加 apt 源。我这里直接给出阿里云镜像的写法因为官方域名在某些网络环境下经常拉不动换成国内镜像源后速度差异明显echo deb [archamd64 signed-by/usr/share/keyrings/docker-archive-keyring.gpg] https://mirrors.aliyun.com/docker-ce/linux/debian $(lsb_release -cs) stable /etc/apt/sources.list.d/docker.list注意这里的archamd64对应的是 CPU 架构。如果跑在树莓派或者 ARM 机器上要改成archarm64否则会提示无法识别软件包。龙芯等 LoongArch 架构要注意官方仓库目前还没有对应的包需要到龙芯自己的移植源里找对应版本直接套用 x86 命令会失败。添加完源之后更新并安装apt update apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin这里和老的安装方式有个明显区别以前还要单独装docker-compose这种 Python 包现在官方已经集成到docker-compose-plugin插件里直接支持docker compose子命令比单独装二进制方便很多也避免了很多版本不匹配的坑。2.2 用 Debian 自带源安装能装但版本偏老如果你懒得多配源Debian 自带的软件仓库里也有 Docker一条命令解决apt install -y docker.io这条命令确实快装完就能用但里面有几个问题一是包版本通常比官方仓库旧新特性、安全修复都滞后二是containerd、docker compose、buildx这些组件不会自动配齐后面用起来还得手动补装麻烦。适合企业内部完全无法访问外网、只能从本地源离线安装的场景。能联网的话我还是建议走官方源。2.3 二进制手动安装只适合完全离线的特殊环境内网隔离、物理断网的机器用 apt 源安装不现实这时候可以下载 Docker 官方提供的静态二进制包解压后手动部署。思路是在一台能联网的机器上从 Docker 官方 release 页面下载对应架构的docker-version.tgz传到目标机器解压把二进制文件放到/usr/bin再手动写 systemd 服务文件实现开机自启。这个方案的缺点很明显版本升级、依赖维护全靠自己还不带containerd之外的一堆配套组件。不是万不得已不太建议日常使用。如果有离线需求更推荐在一台相同 Debian 版本和架构的机器上先把官方源配好、装好 Docker再用dpkg把docker-ce等几个核心包导出来到内网里安装比纯手动放二进制省心得多。3. 装完立刻做这三件事加速器、免 sudo、开机自启Docker 装好之后不要急着跑容器先处理三件小事。这三件事直接影响后面的使用体验尤其是“下载镜像卡死”和“必须加 sudo”这两个高频问题。3.1 配置镜像加速器解决 Docker 拉取慢Docker 默认从 Docker Hub 拉镜像国内网络访问它经常很慢几百 MB 的镜像能拉到怀疑人生。解决办法是在 Docker 配置文件里指定 registry mirror 镜像加速器。编辑/etc/docker/daemon.json没有就新建{ registry-mirrors: [ https://docker.m.daocloud.io ] }如果你有阿里云账号登录容器镜像服务的控制台可以拿到一个形如https://xxxx.mirror.aliyuncs.com的专属加速地址这个地址优先级更高填入数组里的第一项即可公共加速地址放在后面当备用。改完配置重启 Dockersystemctl daemon-reload systemctl restart docker验证是否生效docker info | grep -A 5 Registry Mirrors能看到刚才填的地址说明配置成功。之后再拉mysql:8.0、redis:7这些常用镜像速度会明显提升。3.2 将当前用户加入 docker 组告别 sudo 权限错误刚装完 Docker你会发现执行docker ps会报权限错误permission denied while trying to connect to the Docker daemon socket。这是因为 Docker 的 socket 文件默认归 root 所有普通用户没权限访问。解决办法不是给每条命令加 sudo而是把当前用户加进 docker 组usermod -aG docker $USER newgrp docker然后重新登录服务器再执行docker ps会发现权限错误消失了。这里有个重点加组之后当前会话不会立刻生效必须重新登录一次或者执行newgrp docker切换一下组身份。我遇到很多人加完组还报错其实就是没重新登录。3.3 设置 systemd 开机自启服务器一重启Docker 服务必须跟着起来systemctl enable --now dockerenable负责开机自启--now表示当前立刻启动。然后验证整个 Docker 是否正常docker version docker run hello-worldhello-world会输出一段提示说明 Docker 的安装和运行环境都正常。如果到了这一步整个 Docker 安装流程就结束了接下来可以开始跑真实业务。4. 直接上生产场景MySQL、Redis 主从、GitLab 一轮跑起来很多人装完 Docker 不知道下一步干嘛。我直接从三个常见场景演示覆盖数据库、缓存和代码托管。这些场景把数据卷挂载、网络配置、时区编码这些核心问题全部暴露出来。4.1 MySQL 8.0 容器数据卷、时区、编码一个都不能少MySQL 8.0 是当前最常用的数据库版本用 Docker 跑它比在 Debian 上直接用 apt 装省太多事升级、备份、迁移都方便。我先创建数据目录防止容器删了数据全丢mkdir -p /opt/mysql/conf /opt/mysql/data然后在/opt/mysql/conf/my.cnf里写一份基础配置重点是字符集[mysqld] character-set-serverutf8mb4 collation-serverutf8mb4_unicode_ci [client] default-character-setutf8mb4虽然 MySQL 8.0 默认字符集已经是 utf8mb4但显式写出来能避免有些老客户端连接后出现中文乱码。接下来启动容器docker run -d \ --name mysql8 \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORDYourPassw0rd \ -e TZAsia/Shanghai \ -v /opt/mysql/conf:/etc/mysql/conf.d \ -v /opt/mysql/data:/var/lib/mysql \ mysql:8.0这条命令里几个参数是重点-e MYSQL_ROOT_PASSWORD是第一次初始化时必须指定的 root 密码如果不指定容器会随机生成一个密码还要去日志里翻很麻烦。-e TZAsia/Shanghai控制时区。不加的话容器默认 UTC 时间插入的数据比北京时间慢 8 小时排查问题时会非常头疼。-v /opt/mysql/data把数据库文件持久化到宿主机容器删了重建数据还在。-v /opt/mysql/conf覆盖容器内的 MySQL 配置目录。启动后验证docker exec -it mysql8 mysql -uroot -p SHOW VARIABLES LIKE character_set_server%;看到utf8mb4说明字符集没问题。再执行select now();看看时间是不是北京时间。4.2 Redis 主从一条 master 和一条 slave 容器Redis 主从是常见的缓存架构用 Docker 搭比在物理机上搭简单得多。先建一个独立的 Docker 网络让容器之间能通过容器名互相访问docker network create redis-net启动主节点并开启 AOF 持久化docker run -d \ --name redis-master \ --network redis-net \ -p 6379:6379 \ redis:7 redis-server --appendonly yes然后启动从节点通过--replicaof指定主节点地址。在同一个 Docker 网络里可以直接用容器名redis-master代替 IP 地址docker run -d \ --name redis-slave1 \ --network redis-net \ -p 6380:6379 \ redis:7 redis-server --replicaof redis-master 6379验证主从状态docker exec -it redis-slave1 redis-cli info replication输出里的role:slave和master_link_status:up就说明主从已经建立。如果想继续加从库照着redis-slave1的命令再复制一份换名字换成redis-slave2就行几乎零成本。这里有个生产建议用容器名而不是 IP 做replicaof因为容器重建后 IP 会变而容器名只要在网络里唯一就不会变。这个思路也适用于所有容器之间的互相通信。4.3 GitLab 容器内存不够真的会卡GitLab 是很多团队自建代码托管平台的首选但它是内存大户。如果你只有 2G 内存的机器跑 GitLab 会非常吃力至少 4G 打底。启动命令如下docker run -d \ --name gitlab \ --hostname gitlab.example.com \ -p 10443:443 -p 1080:80 -p 1022:22 \ -v /opt/gitlab/config:/etc/gitlab \ -v /opt/gitlab/logs:/var/log/gitlab \ -v /opt/gitlab/data:/var/opt/gitlab \ --restart always \ gitlab/gitlab-ce:latest注意我把宿主机的 1080 端口映射到容器内的 80 端口因为 80 端口经常被其他服务占用。另外 22 端口如果被 SSH 占了就用 1022 映射容器内的 SSH 端口。首次启动时 GitLab 会初始化数据库、编译资源这个过程可能持续好几分钟期间容器状态是starting这是正常的。等几分钟后先改配置文件把访问地址设对vim /opt/gitlab/config/gitlab.rb修改external_urlexternal_url http://gitlab.example.com改完执行docker exec gitlab gitlab-ctl reconfigure等 reconfigure 跑完浏览器访问http://服务器IP:1080就能看到 GitLab 界面。初始 root 密码在配置文件里会自动生成用docker exec gitlab grep Password: /etc/gitlab/initial_root_password查看。如果是给个人或者小团队用GitLab 其实有点重。追求轻量的话Gitea 是更好的选择几百 MB 内存就能跑用法和 GitHub 很像但这是另一个话题这里不多展开。5. Docker 日常使用镜像、日志、Compose 编排与清理容器跑起来只是开始如何拉镜像不卡、如何管理编排、如何清理磁盘垃圾才是平时的重点。这几块内容我按照使用频率从高到低整理。5.1 镜像下载慢改配置、换标签、清垃圾三板斧镜像下载慢是 Docker 使用里遇到最多的问题解决办法按性价比排列第一板斧是配加速器已经在前文写过了这是最有效的一招。第二板斧是拉取镜像时尽量指定具体版本比如mysql:8.0而不是直接用mysql:latest。latest标签会在上游更新时改变指向你第二次 pull 可能要重新拉整个镜像但固定 tag 的镜像层基本不变只有在确实有新版时才会增量拉取速度快得多。第三板斧是定期清理本地的悬空镜像。Docker 更新镜像时经常残留none标签的旧镜像日积月累非常占空间docker image prune想更彻底清理没被容器引用的镜像docker image prune -a执行前先看看docker system df它会告诉你镜像、容器、数据卷各占了多少空间避免误删正在用的东西。5.2 用 docker compose 编排 Redis 主从一条命令拉起整个环境前面 Redis 主从用docker run敲了两条命令如果还要加哨兵、加监控再继续docker run就不好维护了。这时候用 Compose 文件把整个拓扑描述清楚一条命令就能全部拉起。在/opt/redis/compose.yaml里写入配置services: redis-master: image: redis:7 container_name: redis-master command: [redis-server, --appendonly, yes] ports: - 6379:6379 networks: - redis-net redis-slave1: image: redis:7 container_name: redis-slave1 command: [redis-server, --replicaof, redis-master, 6379] depends_on: - redis-master ports: - 6380:6379 networks: - redis-net networks: redis-net: driver: bridge然后在/opt/redis目录下执行docker compose up -dCompose 会自动创建网络、按依赖顺序启动容器。这个文件放到 Git 仓库里管理以后新机器上直接docker compose up -d就能还原整套环境比手动敲命令靠谱得多。这就是所谓“基础设施即代码”的最小实践。如果你要在生产环境部署更复杂的服务比如微服务项目Compose 也是入门的最佳选择。把每个服务写成一个 service再加上外部依赖和数据卷基本就能把一套可交付的环境描述清楚。5.3 常用 Docker 命令和日志清理日常用得最多的几个命令我列在这里都属于高频中的高频查看运行中的容器docker ps查看所有容器包括已停止的docker ps -a查看容器日志比如 MySQL 起不来时排查原因docker logs --tail 200 mysql8进入容器内部执行命令docker exec -it mysql8 bash查看 Docker 总体的磁盘占用排查机器磁盘满了的问题docker system df超级清理把所有停止的容器、无用网络、悬空镜像、构建缓存全部删掉docker system prune -a开发机上的场景也顺带提一句用 IntelliJ IDEA 这类 IDE 时装好 Docker 插件可以直接连接远程 Docker daemon在 IDE 里看日志、进容器、一键构建镜像。Go 项目在 1.21 之后基础镜像体积明显增大建议用多阶段构建把一个几百 MB 的构建环境镜像压成几十 MB 的运行镜像这个在 IDEA 里配置好 Dockerfile 后基本是自动化的工作流。6. 安装和运行中的高频报错速查手册最后这部分是重头戏。我把安装和运行过程里最高频的报错整理成一张速查表每个问题都是真实踩过或者帮别人解决的。6.1 报错对照速查表报错现象可能原因处理办法permission denied while trying to connect当前用户不在 docker 组usermod -aG docker $USER重新登录Cannot connect to the Docker daemon at unix:///var/run/docker.sockDocker 服务没启动systemctl status dockersystemctl start dockervirtualisation support not detecteddocker desktop failed to startWindows/macOS 上 Docker Desktop 需要硬件虚拟化进 BIOS 开启 VT-x/AMD-V在 Windows 功能里启用 Hyper-V 和 WSL2failed to connect to the docker api at npipe:////./pipe/dockerdesktoplinuxenDocker Desktop 服务没起来或安装不完整确认 Docker Desktop 正常运行重启 Docker Desktop镜像下载速度极慢没有配置镜像加速器编辑/etc/docker/daemon.json配置 registry-mirrors 后重启unable to locate package docker-ceCPU 架构和软件源里的arch不匹配检查archamd64是否对应机器架构换成arm64或对应架构The repository ... does not have a Release file添加了不支持的 Debian 版本代号确认lsb_release -cs输出的版本代号在官方支持列表内容器启动后马上退出前台进程异常退出或配置不正确docker logs 容器名查看日志主机端口被占用容器端口映射冲突换宿主端口比如把-p 3306:3306改成-p 3307:3306这里面有两个典型的“跨平台坑”第一个是virtualisation support not detected。这个报错虽然常见于 Windows 和 macOS 的 Docker Desktop但本质是硬件虚拟化没开。如果你的机器跑过虚拟机软件通常没问题但如果是一台刚买的品牌机或者轻薄本BIOS 里默认可能关着虚拟化需要在开机时进 BIOS 开启 Intel VT-x 或者 AMD-V然后再在 Windows 功能里勾选 WSL2 和 Hyper-V最后重装或重启 Docker Desktop 才会生效。我见过不少人卡在这步检查了无数遍软件就是没查 BIOS。第二个是 npipe 报错failed to connect to the docker api at npipe:////./pipe/dockerdesktoplinuxen。这是 Docker Desktop 在 Windows 上的一个典型故障基本上和 Debian 服务器无关而是 Docker Desktop 自己没起来。优先重启 Docker Desktop再看右下角托盘图标是否变绿不用急着重装。6.2 几个容易被忽略的操作细节报错表之外还有几个操作习惯层面的提醒。防火墙不要只放行 SSH 端口。如果你用ufw或者别的防火墙容器端口映射出来的端口也要同步放行比如 MySQL 映射了 3306防火墙没放行客户端会一直连接超时。不过要注意Docker API 默认管理的 2375 端口千万不要裸暴露到公网这等于把服务器钥匙挂门口非常危险。用 Docker 时尽量通过容器端口映射来提供服务不要直接开放 daemon 的 TCP 端口。磁盘空间要提前规划。Docker 默认数据目录在/var/lib/docker如果系统盘本来就不大镜像和容器日志很容易把它填满机器会出现各种莫名其妙的问题。最简单粗暴的方式是装完系统就把大块数据盘挂载到/var/lib/docker或者在安装前规划好这个目录的存储空间。数据卷备份要养成习惯。容器本身是“短命”的删掉重建很正常但挂在宿主机的数据卷才是真正的资产。我备份环境时从来不做docker commit而是直接备份/opt/mysql、/opt/gitlab这些挂载目录体积直观恢复也快比备份镜像要实在得多。最后再分享一个我自己的操作习惯装任何一台 Debian 机器顺序永远是先固定 IP、再配 SSH 免密、最后装 Docker。表面上看这些事和 Docker 没有直接关系但只要容器服务一跑起来IP 变了、会话断了、权限不对排查成本会翻好几倍。把这个顺序固定成肌肉记忆以后后面部署任何服务都会顺很多。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门