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

Ubuntu 24.04上Docker部署PostgreSQL完整实操记录

我在这台腾讯云服务器上用Docker部署PostgreSQL踩了不少坑官方文档写得云里雾里网上教程又大多针对旧版本系统很多命令在Ubuntu 24.04上直接跑不通。折腾了一整天总算把整套流程捋顺了从零到生产可用包括远程连接、权限配置、数据持久化这些关键环节现在整理成这篇实操记录希望对正在折腾的人有帮助。说实话Ubuntu 24.04刚推出来的时候我还在犹豫要不要把服务器系统升级上去。毕竟作为长期支持版本官方保证支持到2029年安全性更新和软件源维护都有保障最终决定拿这台腾讯云服务器当小白鼠。结果发现24.04相比22.04在几个底层库上变动挺大直接导致我之前熟悉的那套部署流程全部要重新验证。特别是Docker的安装方式和PostgreSQL容器的兼容性都有不少值得注意的细节。1. 部署方案设计与核心思路1.1 为什么选择Docker方式部署PostgreSQL在云服务器上部署PostgreSQL无非就三条路apt直接安装、编译源码安装、Docker容器化部署。我个人的建议是除非你有极度定制化的需求否则优先选Docker理由很实在。apt源里的PostgreSQL版本通常滞后Ubuntu 24.04官方源里默认的还是PostgreSQL 16但PostgreSQL 17都已经发布一段时间了。如果你需要尝鲜或者生产环境有特定版本要求apt这条路基本就走不通了。编译安装更折腾依赖库、编译参数、后续维护全得自己操心光是处理那一堆依赖关系就够写一篇文章了。Docker部署的核心优势在于环境隔离和版本管理。我在这台腾讯云服务器上同时跑了多个项目每个项目对数据库版本的要求可能都不一样有的要PostgreSQL 15有的要16Docker可以让你在一台机器上完美共存互不干扰。而且容器级别的资源限制、日志管理、启动策略都比裸机部署要精细得多。1.2 部署架构与关键决策我这次部署采用单机单容器架构目录规划如下PostgreSQL数据目录挂载到宿主机/data/postgresql确保容器删除后数据不丢失配置目录独立挂载方便直接修改配置文件而不必进入容器日志输出到宿主机/data/postgresql/logs便于集中查看和日志采集选择这个架构主要基于三点考虑。数据安全永远是第一位的Docker容器本身是瞬态的随时可能被删除重建如果数据存放在容器内部一旦误删容器数据就彻底没了。其次是运维方便直接在宿主机上用vim修改配置文件然后重启容器比进入容器操作要顺手得多。最后是适配腾讯云的监控体系后续如果要接入云监控或者日志服务日志在宿主机上会好处理很多。2. 服务器基础环境配置2.1 系统初始设置拿到一台全新的腾讯云服务器第一步别急着装Docker先把系统基础环境调理好。我习惯用如下顺序操作# 以root用户登录后先更新软件源和系统 apt update apt upgrade -y # 安装基础工具包 apt install -y wget curl vim git lrzsz net-tools # 设置时区为Asia/Shanghai timedatectl set-timezone Asia/Shanghai # 创建软件安装目录 mkdir -p /data/software /data/postgresql时区设置这个细节很容易被忽略但影响特别大。如果你不设置时区默认的UTC时间那么PostgreSQL的NOW()函数返回的时间会比北京时间慢8小时。这个时间偏差在开发和联调阶段会让你抓狂特别是做日志分析、定时任务调试的时候。2.2 Ubuntu 24.04的apt源优化Ubuntu 24.04的apt源在国内访问有时候不太稳定尤其在你执行apt update的时候那个速度简直让人怀疑人生。腾讯云服务器可以很方便地使用内网镜像源不仅快而且不消耗公网流量。# 备份原始源文件 cp /etc/apt/sources.list /etc/apt/sources.list.bak # 直接替换为腾讯云镜像源 cat /etc/apt/sources.list EOF deb http://mirrors.cloud.tencent.com/ubuntu/ noble main restricted universe multiverse deb http://mirrors.cloud.tencent.com/ubuntu/ noble-updates main restricted universe multiverse deb http://mirrors.cloud.tencent.com/ubuntu/ noble-backports main restricted universe multiverse deb http://mirrors.cloud.tencent.com/ubuntu/ noble-security main restricted universe multiverse EOF apt update这里特别提醒一下Ubuntu 24.04的代号是noble不是之前的jammy如果照抄22.04的命令会直接报错。我之前就吃过这个亏复制了旧命令然后发现一堆404错误排查了半天才发现是源地址的问题。3. Docker引擎安装与加速配置3.1 Docker安装的几种方式Ubuntu 24.04上安装Docker官方推荐用apt仓库安装我也建议正常情况都走这条路。虽然我见过有人直接用snap install docker省事儿是省事儿但后续管理权限、自定义配置会比较麻烦而且在Ubuntu 24.04上snap版Docker偶尔会有奇怪的兼容性问题不建议在服务器环境使用。# 安装依赖包 apt install -y apt-transport-https ca-certificates curl gnupg lsb-release # 添加Docker官方GPG密钥 curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg # 设置Docker apt仓库 echo deb [archamd64 signed-by/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable | tee /etc/apt/sources.list.d/docker.list /dev/null # 安装Docker引擎 apt update apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin需要提醒的是我们在服务器上直接运行了docker命令但没用sudo这样操作起来最顺手。但Docker和系统安全息息相关在当前的安全环境下确保你完全清楚自己在做什么再这么配置。# 将当前用户加入docker组免sudo执行docker命令 usermod -aG docker $USER newgrp docker # 设置Docker开机自启 systemctl enable docker systemctl start docker # 验证安装 docker --version docker compose version3.2 配置镜像加速器Docker镜像拉取速度在国内一直是个痛点尤其是从Docker Hub直接拉取PostgreSQL官方镜像那个速度简直折磨人。腾讯云服务器可以配置使用腾讯云的Docker镜像加速器速度快很多。mkdir -p /etc/docker cat /etc/docker/daemon.json EOF { registry-mirrors: [https://mirror.ccs.tencentyun.com] } EOF systemctl daemon-reload systemctl restart docker腾讯云这个镜像加速地址只对腾讯云服务器内网有效如果你用的是其他厂商的服务器或者本地虚拟机这个地址是访问不了的。如果你用阿里云服务器可以换用阿里云的加速器如果是在本地环境我试过配置几个公共加速器效果都不太稳定最后干脆把代理环境配好直接拉取。3.3 验证Docker环境什么都配置好之后强烈建议先拉一个小镜像测试一下别一上来就拉PostgreSQL。踩过的坑用hello-world先确认Docker全家桶工作正常然后再拉取PostgreSQL镜像这样万一出问题至少能隔离开来是Docker自身问题还是PostgreSQL镜像问题。docker pull hello-world docker run --rm hello-world # 看到Hello from Docker!提示说明Docker环境正常4. PostgreSQL容器镜像选择与部署4.1 镜像版本选择策略Docker Hub上的PostgreSQL官方镜像版本非常多从9.x到17.x都有。很多人习惯直接docker pull postgres:latest这样省事但生产环境我强烈不建议这么做这是给自己埋雷。你怎么知道你下次启动容器时的latest变成了什么版本呢我的建议是明确指定大版本号。比如当前要部署的目标环境PostgreSQL 16是最稳定的长期支持版本就和Ubuntu 24.04搭配得很默契。需要说明的是PostgreSQL的小版本升级不需要重新初始化数据目录直接拉取新的小版本镜像重新启动容器即可。# 拉取PostgreSQL 16.x版本镜像 docker pull postgres:16 # 查看本地已有镜像 docker images4.2 使用docker-compose编排部署docker run虽然简单直观但每次要写一长串参数而且不好维护。我更推荐用docker-compose尤其当你需要多容器编排的时候比如数据库加应用容器compose文件的优势立刻就体现出来了。在/data/postgresql目录下创建docker-compose.yml文件services: postgresql: image: postgres:16 container_name: postgresql restart: always environment: POSTGRES_USER: myadmin POSTGRES_PASSWORD: YourStrongPassw0rd! POSTGRES_DB: myapp TZ: Asia/Shanghai PGTZ: Asia/Shanghai ports: - 5432:5432 volumes: - /data/postgresql/data:/var/lib/postgresql/data - /data/postgresql/logs:/var/log/postgresql shm_size: 256mb healthcheck: test: [CMD-SHELL, pg_isready -U myadmin -d myapp] interval: 10s timeout: 5s retries: 5关于这个compose文件有几个点值得展开说明。restart: always非常重要有了这个配置Docker守护进程启动时会自动拉起PostgreSQL容器同时如果容器因为异常退出也会自动重启。之前我在测试环境就是忘了写这个服务器重启后数据库没起来排查了半天才发现是这个问题。POSTGRES_USER和POSTGRES_PASSWORD这两个环境变量是PostgreSQL官方镜像的“首次启动”配置。也就是说只有在数据目录为空的时候镜像的entrypoint脚本才会去读取这些变量创建用户和数据库。如果数据目录已经有数据了这些环境变量会被忽略。明白这个机制后你就知道为什么有时候改了密码环境变量但不起作用——因为你的数据目录已经初始化过了。PGTZ这个环境变量容易被忽略它控制的是PostgreSQL会话内部的时区。虽然我在宿主机层面设置了TZ但PostgreSQL的默认时区行为有时候不按常理出牌显式设置PGTZ能确保数据库层面的时间计算也是正确的北京时间。4.3 启动容器并验证cd /data/postgresql docker compose up -d # 查看容器状态 docker ps # 查看容器日志 docker logs -f postgresql等日志稳定输出之后可以进一步验证数据库连通性# 进入容器内部执行SQL docker exec -it postgresql psql -U myadmin -d myapp # 执行一些基础验证SQL SELECT version(); SELECT now(); SHOW timezone;正常情况下version()应该显示PostgreSQL 16.xnow()应该是北京时间timezone应该是Asia/Shanghai。到这里单机部署的核心环节就已经完成了。5. 远程连接配置与安全加固5.1 修改监听地址与认证方式PostgreSQL默认只监听localhost也就是只允许本机连接。要远程连接必须修改两个地方监听地址和认证方式。PostgreSQL 16基于安全考虑镜像里的postgresql.conf默认配置将listen_addresses设置成了localhost。Docker容器内部其实很特殊因为容器有自己的网络命名空间即使设置监听*也只暴露在容器的网络栈中通过端口映射才能从宿主机访问。所以这里可以放心修改。# 进入容器并修改配置 docker exec -it postgresql bash # 在容器内执行 sed -i s/#listen_addresses localhost/listen_addresses */ /var/lib/postgresql/data/postgresql.conf # 退出容器重启使其生效 exit docker restart postgresql同时要修改客户端认证配置pg_hba.conf添加允许远程连接的规则# 编辑pg_hba.conf在文件末尾追加 echo host all all 0.0.0.0/0 scram-sha-256 /data/postgresql/data/pg_hba.conf # 重启容器 docker restart postgresql关于认证方式PostgreSQL 16的默认密码加密方式是scram-sha-256这一点比旧版本的md5要安全得多。修改配置时务必保留默认的scram-sha-256不要因为看着md5眼熟就改回md5。5.2 腾讯云安全组与防火墙配置腾讯云服务器有两层网络防线安全组是云平台层面的虚拟防火墙ufw是系统层面的防火墙两层都要放行5432端口。先看系统层面的防火墙ufw allow 5432/tcp ufw status再登录腾讯云控制台找到这台服务器实例确认安全组入站规则中放行了TCP 5432端口。这一步最容易卡住系统防火墙放行了但云平台安全组没开就是连不上。很多人排查半天最后发现是安全组的事这个坑我踩过不止一次。5.3 安全加固经验数据库端口暴露到公网安全压力是巨大的。如果你只是自己用或者团队内部使用有更好的方案。最稳妥的做法是修改默认端口。把宿主机映射端口从5432改成非常规端口比如54321虽然这种做法挡不住有耐心的攻击者但能过滤掉绝大多数自动化扫描脚本因为他们默认只会扫5432端口。其次密码必须足够复杂。我见过太多数据库弱口令被爆破的案例有些人设置密码喜欢用公司名加生日这种密码在字典库里基本是一击即中。建议用至少16位包含大小写字母、数字、特殊字符的随机密码用密码管理器生成并保存。如果是纯内网使用或者个人开发环境更建议配合腾讯云安全组设置IP白名单只允许特定IP访问5432端口。比如你的办公网固定IP或者你家里的宽带IP这样安全等级立刻提升好几个档次。我在生产环境一般就是数据库不直接暴露公网而是通过跳板机转发访问虽然多了一步操作但安全性完全不是一个量级。6. 数据持久化与备份策略6.1 数据持久化验证刚部署完数据库很多人会有疑问万一容器挂了怎么办重启后数据还在吗要验证数据持久化是否配置正确最直接的办法就是实际测试一下。# 创建测试数据 docker exec -it postgresql psql -U myadmin -d myapp -c CREATE TABLE test(id serial primary key, name text); docker exec -it postgresql psql -U myadmin -d myapp -c INSERT INTO test(name) VALUES(持久化测试); # 强制删除容器模拟灾难场景 docker compose down docker compose up -d # 验证数据是否还在 docker exec -it postgresql psql -U myadmin -d myapp -c SELECT * FROM test;如果你能看到之前插入的数据说明数据持久化没问题。这里的关键就在volume挂载配置/data/postgresql/data映射到了容器内部的/var/lib/postgresql/data这个目录在镜像的Dockerfile中被声明为VOLUME所有数据文件都在这里。多数情况下如果忘记了配置数据目录挂载容器一删数据库就彻底没了连恢复的机会都没有。那种数据丢失的感觉经历过的人都懂比被老板骂一顿还难受。6.2 定时备份方案数据持久化只是第一步定期备份才是数据安全的终极防线。我喜欢用crontab加pg_dump的方式简单可靠不需要额外装复杂的备份工具。# 创建备份脚本 cat /data/postgresql/backup.sh EOF #!/bin/bash BACKUP_DIR/data/backup/postgresql BACKUP_FILE$BACKUP_DIR/myapp_$(date %Y%m%d_%H%M%S).sql KEEP_DAYS7 mkdir -p $BACKUP_DIR # 使用docker exec执行pg_dump docker exec postgresql pg_dump -U myadmin -d myapp $BACKUP_FILE # 压缩备份文件 gzip $BACKUP_FILE # 清理7天前的备份 find $BACKUP_DIR -name *.sql.gz -mtime $KEEP_DAYS -exec rm {} \; # 输出备份结果 echo Backup completed at $(date) /data/postgresql/backup.log EOF chmod x /data/postgresql/backup.sh # 配置每天凌晨2点执行备份 echo 0 2 * * * /data/postgresql/backup.sh | crontab -这个备份方案的思路是每天凌晨2点用pg_dump导出完整的SQL文件压缩后保留7天既保证了可以恢复到任意一天的数据状态又不会让磁盘被备份文件塞满。如果你的数据库特别大可以考虑用pg_basebackup做物理备份或者用WAL-G做持续归档但绝大多数中小项目用逻辑备份就够了。生产环境的话建议把备份文件再同步一份到腾讯云COS对象存储异地容灾级别。这个可以通过腾讯云自带的coscmd工具轻松实现加几行命令就行。注意安全第一备份密码文件或环境变量不要硬编码在脚本里避免泄露。提示腾讯云存储等云服务都可以配合这些备份策略但要注意访问密钥的权限控制。尽量减少密钥泄露的风险只授予必要的读写权限不要用主账号密钥。7. 常见故障排查与优化实践7.1 容器启动失败症状执行docker compose up -d后容器状态是Exited或者一直在Restarting。排查方法# 查看容器日志这是最直接的线索 docker logs postgresql常见的错误就是端口被占用。你之前用apt装过PostgreSQL宿主机5432端口已经被占用了容器内的PostgreSQL无法绑定这个端口。解决方式是先停掉并卸载宿主机自带的PostgreSQL或者修改宿主机的映射端口。另一个常见问题是数据目录权限不匹配。容器内的PostgreSQL是以postgres用户UID 999运行的挂载到宿主机后如果宿主机上的/data/postgresql/data目录所属用户不是UID 999容器就报权限错误无法写入数据文件。我遇到过这种情况排查了很久才发现是权限问题后面学乖了直接在创建数据目录的时候就把属主设置为UID 999mkdir -p /data/postgresql/data chown -R 999:999 /data/postgresql/data7.2 认证失败与密码修改症状在本机用psql连接提示password authentication failed for user myadmin。可能的原因首次启动创建用户时环境变量设置错误导致密码不是你想设的那个pg_hba.conf里配置的认证方式和实际用的密码加密方式不匹配数据目录在创建用户之前就已经初始化过了环境变量根本没生效针对最麻烦的情况就是环境变量没生效但数据目录已经初始化。这时候需要手动修改密码# 进入容器 docker exec -it postgresql psql -U myadmin -d myapp # 执行SQL修改密码 ALTER USER myadmin WITH PASSWORD NewStrongPassword;注意如果你的pg_hba.conf里配的是scram-sha-256这个密码切换没问题因为新密码会自动用当前配置的加密方式存储。7.3 远程连接超时或拒绝连接症状从本地电脑用pgAdmin或psql连接腾讯云服务器上的PostgreSQL提示超时或者connection refused。排查顺序按可能性从高到低排列腾讯云安全组是否放行了5432端口系统防火墙ufw是否放行PostgreSQL是否监听了*或0.0.0.0pg_hba.conf是否允许你的IP网段访问网络是否通可以先telnet 服务器IP 5432试试这里想说的是排查问题不要靠猜要按照网络连通性的层次从外往内排查先确认端口通不通再确认监听地址最后看认证配置。我见过很多同事一上来就修改PostgreSQL配置结果问题其实出在安全组。7.4 性能优化基础配置PostgreSQL容器默认配置偏保守大致适合小内存的虚拟机环境。如果你的腾讯云服务器内存有4GB或更多建议调整几个核心参数。# 修改postgresql.conf shared_buffers 1GB effective_cache_size 3GB maintenance_work_mem 256MB work_mem 16MB max_connections 200这几个参数的含义用大白话解释一下。shared_buffers是PostgreSQL在内存里缓存数据的缓冲区大小通常设置为物理内存的1/4effective_cache_size是对操作系统文件缓存的一个估计值影响查询规划器的决策通常设置为物理内存的50%~75%work_mem是单个查询排序、哈希操作能用的内存不要设置太大否则高并发场景下内存直接爆掉max_connections控制最大连接数默认100对于小项目够用但如果你用连接池可以适当调大。如果不确定建议先保持默认配置观察实际负载再调整。机器性能问题要具体分析不要一上来就改参数很多时候压垮数据库的是慢查询而不是配置不够好。8. 部署验证与上线检查清单8.1 功能验证清单在正式使用之前可以从下面几个维度全面验证数据库的可用性数据库连接是否正常本机和远程分别测试数据是否持久化删除容器重建后数据不丢服务是否自动重启宿主机重启后容器自动拉起备份流程是否正常能完整导出并恢复日志是否正常输出并且有合理的轮转策略8.2 最佳实践总结这次在腾讯云上部署PostgreSQL有几个特别想分享的心得。不要在生产环境使用latest标签的镜像锁定大版本号是对未来自己的负责。前后端协作时环境不一致的锅甩起来很累锁定版本后大家起码有一个共同基线。密码管理要安全数据库密码不要写在明文的配置文件或环境变量里。我见过很多公司PostgreSQL密码直接写在.env文件里传到Git仓库的那种泄漏风险比黑客攻击还大。可以考虑用Docker secret或者外部密钥管理服务来保存敏感配置。关于数据目录强烈建议不要和数据库容器放在同一块系统盘上。腾讯云服务器可以单独挂载数据盘把/data挂到独立的数据盘上这样即使系统盘故障数据也还在。这个我在生产环境吃过亏系统盘崩溃重装系统后数据盘直接挂载到新系统就能恢复数据省去了很多麻烦。最后特别提醒一下不要在容器里额外安装软件比如用apt装vim、net-tools之类的工具。容器应该是不可变基础设施想改配置就修改挂载到宿主机的配置文件然后重启想装工具就在宿主机上装。保持容器的纯净既有利于镜像复用也方便后续升级迁移。
分享:

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

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