如何在官方PostgreSQL Docker镜像中配置sshd服务自动启动
问题描述
我正尝试在多台Docker主机上搭建PostgreSQL-Pgpool集群,已在postgres:13-bullseye镜像中安装openssh-server,但无法在容器启动时自动启动sshd服务。尝试过以下配置:
entrypoint: ["bash -c '/usr/local/bin/docker-entrypoint.sh postgres && service ssh start'"]
也试过将PostgreSQL入口命令与service ssh start一同写入Dockerfile的entrypoint,或在Dockerfile配置entrypoint后在docker-compose中设置command,但这些操作都会影响PostgreSQL的正常启动。目前集群配置未完成,希望先解决sshd服务自动启动的问题。
我的配置文件
Dockerfile
FROM postgres:13-bullseye AS build USER root ENV http_proxy="http://gateway.zscloud.net:9480" ENV https_proxy="http://gateway.zscloud.net:9480" ENV no_proxy="127.0.0.1, localhost, 192.168., 10." COPY postgres-*.sh /docker-entrypoint-initdb.d/ RUN mkdir /run/sshd && apt-get update && apt-get install -y openssh-server pgpool2 gosu sudo && apt-get clean && echo "postgres ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers.d/postgres && mkdir /var/lib/postgresql/.ssh && chown postgres:postgres /var/lib/postgresql/.ssh && chmod 755 /docker-entrypoint-initdb.d/postgres-*.sh
docker-compose.yml
version: '3.1' services: postgresql: build: context: . dockerfile: Dockerfile container_name: pg_${HOSTNAME} hostname: pg_${HOSTNAME} environment: - http_proxy=http://gateway.zscloud.net:9480 - https_proxy=http://gateway.zscloud.net:9480 - no_proxy=127.0.0.1, localhost, 192.168.*, 10.* - POSTGRES_USER=postgres - POSTGRES_PASSWORD=postgres - PGDATA=/var/lib/postgresql/data ports: - '2345:5432' volumes: - postgres_home:/var/lib/postgresql - postgres_data:/var/lib/postgresql/data - pgpool_etc:/etc/pgpool2 networks: postgresql: ipv4_address: 10.0.3.1 volumes: postgres_home: driver: local postgres_data: driver: local pgpool_etc: driver: local networks: postgresql: external: true
postgres-init.sh
#!/bin/sh set -e cat << EOF >> /var/lib/postgresql/data/pg_hba.conf host replication replicator 10.0.3.1/32 trust host replication replicator 10.0.3.2/32 trust host replication replicator 10.0.3.3/32 trust host replication replicator 10.0.3.4/32 trust host all all all scram-sha-256 EOF cat << EOF >> /var/lib/postgresql/.bash_profile export http_proxy="http://gateway.zscloud.net:9480" export https_proxy="http://gateway.zscloud.net:9480" export no_proxy="127.0.0.1, localhost, 192.168.*, 10.*" export POSTGRES_USER=postgres export POSTGRES_PASSWORD=postgres export PGDATA=/var/lib/postgresql/data export PGPASSFILE="~/.pgpass" EOF cd ~/.ssh ; ssh-keygen -t rsa -b 2048 -q -N "" -f ~/.ssh/id_rsa cat << EOF >> /var/lib/postgresql/.pgpass *:*:*:pgpool:pgpool *:*:*:replicator:replicator *:*:*:postgres:postgres EOF cd ~/data cat << EOF >> /var/lib/postgresql/data/openssl.conf [req] default_bits = 2048 prompt = no default_md = sha256 req_extensions = req_ext distinguished_name = dn [ dn ] C=DE ST=BW L=Stuttgart O=Vector Informatik GmbH OU=Postgres CN=$HOSTNAME.vi.vector.int [ req_ext ] subjectAltName = @alt_names [ alt_names ] DNS.1 = $HOSTNAME.vi.vector.int DNS.2 = $HOSTNAME EOF openssl req -new -x509 -nodes -out server.crt -newkey rsa:2048 -keyout server.key -config /var/lib/postgresql/data/openssl.conf cat << EOF >> /var/lib/postgresql/data/postgresql.conf listen_addresses = '*' password_encryption = scram-sha-256 ssl = on archive_mode = on archive_command = 'cp "%p" "/var/lib/postgresql/data/wal_archive/%f"' max_wal_senders = 100 max_replication_slots = 10 wal_level = replica hot_standby = on wal_log_hints = on primary_conninfo = 'user=replicator password=replicator host=10.0.3.3 port=5432 sslmode=prefer sslcompression=1' primary_slot_name = '$HOSTNAME' wal_keep_size = 100 synchronous_commit = on synchronous_standby_names = 'ANY 1(*)' EOF mkdir /var/lib/postgresql/data/wal_archive psql << END_OF_SQL SET password_encryption = 'scram-sha-256'; ALTER USER postgres PASSWORD 'postgres'; CREATE ROLE pgpool WITH LOGIN; CREATE ROLE replicator WITH REPLICATION LOGIN; ALTER USER pgpool PASSWORD 'pgpool'; ALTER USER replicator PASSWORD 'replicator'; GRANT pg_monitor TO pgpool; END_OF_SQL
解决方案
核心问题是:/usr/local/bin/docker-entrypoint.sh postgres是前台阻塞命令,用&&连接时会卡住后续的sshd启动;同时容器的PID 1进程必须保持前台运行,否则容器会直接退出。以下是两种可靠的解决方法:
方法一:自定义启动脚本(轻量方案)
- 在项目目录创建
start-services.sh脚本:
#!/bin/bash set -e # 后台启动sshd /usr/sbin/sshd # 执行PostgreSQL官方entrypoint并保持前台运行(容器PID 1) exec /usr/local/bin/docker-entrypoint.sh postgres
- 给脚本添加执行权限:
chmod +x start-services.sh
- 修改Dockerfile,复制脚本并设置为entrypoint:
FROM postgres:13-bullseye AS build USER root ENV http_proxy="http://gateway.zscloud.net:9480" ENV https_proxy="http://gateway.zscloud.net:9480" ENV no_proxy="127.0.0.1, localhost, 192.168., 10." COPY postgres-*.sh /docker-entrypoint-initdb.d/ COPY start-services.sh /usr/local/bin/ RUN mkdir /run/sshd && apt-get update && apt-get install -y openssh-server pgpool2 gosu sudo && apt-get clean && echo "postgres ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers.d/postgres && mkdir /var/lib/postgresql/.ssh && chown postgres:postgres /var/lib/postgresql/.ssh && chmod 755 /docker-entrypoint-initdb.d/postgres-*.sh && chmod +x /usr/local/bin/start-services.sh ENTRYPOINT ["start-services.sh"]
- 移除docker-compose中的entrypoint配置,让镜像使用自定义入口。
方法二:用Supervisord管理多进程(稳定方案)
如果需要监控进程状态、自动重启服务,推荐用Supervisord:
- 修改Dockerfile安装Supervisord:
FROM postgres:13-bullseye AS build USER root ENV http_proxy="http://gateway.zscloud.net:9480" ENV https_proxy="http://gateway.zscloud.net:9480" ENV no_proxy="127.0.0.1, localhost, 192.168., 10." COPY postgres-*.sh /docker-entrypoint-initdb.d/ COPY supervisord.conf /etc/supervisor/conf.d/ RUN mkdir /run/sshd && apt-get update && apt-get install -y openssh-server pgpool2 gosu sudo supervisor && apt-get clean && echo "postgres ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers.d/postgres && mkdir /var/lib/postgresql/.ssh && chown postgres:postgres /var/lib/postgresql/.ssh && chmod 755 /docker-entrypoint-initdb.d/postgres-*.sh ENTRYPOINT ["/usr/bin/supervisord", "-n"]
- 创建
supervisord.conf配置文件:
[supervisord] nodaemon=true [program:sshd] command=/usr/sbin/sshd -D user=root autostart=true autorestart=true [program:postgresql] command=/usr/local/bin/docker-entrypoint.sh postgres user=postgres autostart=true autorestart=true stdout_logfile=/dev/stdout stdout_logfile_maxbytes=0 stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0
额外注意事项
- 需确保sshd允许登录:检查
/etc/ssh/sshd_config,必要时在Dockerfile中添加修改(比如设置PasswordAuthentication yes、PermitRootLogin no)。 - 在docker-compose的ports中添加
- '2222:22',暴露sshd端口(避免与主机22端口冲突)。
内容的提问来源于stack exchange,提问作者user11236651
相关产品推荐
相关产品推荐

