创建Docker并安装PostgreSQL

#创建docker
docker run --privileged -dit --name test --net staticnet --ip 192.168.2.6 centos-ssh /usr/sbin/init
#安装postgressql11.2
yum install -y https://download.postgresql.org/pub/repos/yum/11/redhat/rhel-7-x86_64/pgdg-centos11-11-2.noarch.rpm
yum install -y postgresql11 postgresql11-server
#初始化data
/usr/pgsql-11/bin/postgresql-11-setup initdb
#设置开机自启并启动
systemctl enable postgresql-11
systemctl start postgresql-11

查看/run/postgresql

[root@06b0e1e15b1b run]# pwd
/run
[root@06b0e1e15b1b run]# ll
total 16
-rw-r--r--  1 root     root       3 Oct 17 17:06 atd.pid
drwxr-xr-x  2 root     root      40 Oct 17 17:11 console
-rw-r--r--  1 root     root       3 Oct 17 17:06 crond.pid
----------  1 root     root       0 Oct 17 17:06 cron.reboot
drwx------  2 root     root      40 Oct 17 17:11 cryptsetup
drwxr-xr-x  2 root     root      60 Oct 17 17:06 dbus
drwxr-xr-x  2 root     root      40 Oct 17 17:11 faillock
drwxr-xr-x  4 root     root      80 Oct 17 17:11 lock
drwxr-xr-x  2 root     root      40 Oct 17 17:11 log
drwxr-xr-x  2 root     root      40 Oct 17 17:06 mount
drwxrwxr-x  2 root     root      40 Oct 17 17:11 netreport
drwxr-xr-x  2 postgres postgres  40 Oct 17 17:17 postgresql
drwxr-xr-x  2 root     root       6 Oct 17 17:06 secrets
drwxr-xr-x  2 root     root      40 Oct 17 17:11 sepermit
drwxr-xr-x  2 root     root      40 Oct 17 17:11 setrans
-rw-r--r--  1 root     root       3 Oct 17 17:06 sshd.pid
drwx--x--x  3 root     root      60 Oct 17 17:11 sudo
drwx------  2 root     root      40 Oct 17 17:11 svnserve
-rw-------  1 root     root       2 Oct 17 17:06 syslogd.pid
drwxr-xr-x 15 root     root     400 Oct 17 17:15 systemd
drwxr-xr-x  2 root     root      40 Oct 17 17:11 user
[root@06b0e1e15b1b run]# ll postgresql/ -a
total 4
drwxr-xr-x  2 postgres postgres  80 Oct 17 17:31 .
drwxr-xr-x 18 root     root     460 Oct 17 17:17 ..
srwxrwxrwx  1 postgres postgres   0 Oct 17 17:31 .s.PGSQL.5432
-rw-------  1 postgres postgres  63 Oct 17 17:31 .s.PGSQL.5432.lock

可以看到/run/postgresql中包含.s.PGSQL.5432.s.PGSQL.5432.lock

重启docker容器

docker restart test

进入容器查看

[root@Server]# docker exec -ti test /bin/bash
[root@06b0e1e15b1b /]# cd /run/
[root@06b0e1e15b1b run]# ll
total 16
-rw-r--r-- 1 root root   3 Oct 17 17:34 atd.pid
-rw-r--r-- 1 root root   3 Oct 17 17:34 crond.pid
---------- 1 root root   0 Oct 17 17:34 cron.reboot
drwxr-xr-x 2 root root  60 Oct 17 17:34 dbus
drwxr-xr-x 2 root root  40 Oct 17 17:34 lock
drwxr-xr-x 2 root root  40 Oct 17 17:34 mount
drwxr-xr-x 2 root root   6 Oct 17 17:34 secrets
-rw-r--r-- 1 root root   3 Oct 17 17:34 sshd.pid
-rw------- 1 root root   2 Oct 17 17:34 syslogd.pid
drwxr-xr-x 8 root root 260 Oct 17 17:34 systemd

重启后会发现/run/postgresql丢失了

问题分析:

执行df

[root@06b0e1e15b1b run]# df
Filesystem     1K-blocks     Used Available Use% Mounted on
overlay         41931776 12979836  28951940  31% /
tmpfs            4005220        0   4005220   0% /dev
/dev/vda1       41931776 12979836  28951940  31% /etc/hosts
shm                65536        0     65536   0% /dev/shm
tmpfs              65536       24     65512   1% /run
tmpfs              65536        0     65536   0% /run/lock
tmpfs              65536        0     65536   0% /var/log/journal
tmpfs            4005220        0   4005220   0% /tmp

发现第7行,/run使用的是tmpfs文件系统,简单来说就是一个基于内存的文件系统,断电重启后系统中的文件不会保存。详见:tmpfs

解决方法:

1.可以手动创建该目录并修改权限
mkdir /run/postgresql
chown -R postgres:postgres postgresql/
2.可以通过systemd-tmpfiles来创建
systemd-tmpfiles --create  /usr/lib/tmpfiles.d/*

因为/run目录的这个特殊性,CentOS7特意在/usr/lib/tmpfiles.d/下提供了可以自定义.conf的方式来解决这个问题。详见:tmpfiles.d

[root@06b0e1e15b1b run]# cat /usr/lib/tmpfiles.d/postgresql-11.conf 
d /run/postgresql 0755 postgres postgres -

PG为我们提供了这个配置文件,这行的意思就是有/run/postgresql就直接设置权限,没有就创建后再设置权限,这个指令在安装PG的时候会执行,因为安装时一般都在root权限下,而执行systemctl start postgresql-11时实际是用/usr/pgsql-11/bin/postmaster -D ${PGDATA}来启动,且使用postgres用户组和用户,导致无法创建该文件夹。而且执行systemctl start postgresql-11看不到任何报错,PG的log中也没有错误日志。只有再切换到postgres用户下执行pg_ctl start才会看到错误,报了Permission denied

bash-4.2$ /usr/pgsql-11/bin/pg_ctl start -D /var/lib/pgsql/11/data
waiting for server to start....2019-10-16 21:21:33.801 CST [277] LOG:  number of prepared transactions has not been configured, overriding
2019-10-16 21:21:33.801 CST [277] DETAIL:  max_prepared_transactions is now set to 200
2019-10-16 21:21:33.802 CST [277] LOG:  listening on IPv4 address "0.0.0.0", port 5432
2019-10-16 21:21:33.802 CST [277] LOG:  listening on IPv6 address "::", port 5432
2019-10-16 21:21:33.805 CST [277] FATAL:  could not create lock file "/var/run/postgresql/.s.PGSQL.5432.lock": Permission denied
2019-10-16 21:21:33.805 CST [277] LOG:  database system is shut down
 stopped waiting
pg_ctl: could not start server
Examine the log output.
3.修复systemd-tmpfiles服务

systemd-tmpfiles服务是可以开机自启的,为什么在docker中就是有问题的,不能执行呢?

[root@06b0e1e15b1b run]# cat /usr/lib/systemd/system/systemd-tmpfiles-setup.service 
#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

[Unit]
Description=Create Volatile Files and Directories
Documentation=man:tmpfiles.d(5) man:systemd-tmpfiles(8)
DefaultDependencies=no
Conflicts=shutdown.target
After=systemd-readahead-collect.service systemd-readahead-replay.service local-fs.target systemd-sysusers.service
Before=sysinit.target shutdown.target
RefuseManualStop=yes

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/systemd-tmpfiles --create --remove --boot --exclude-prefix=/dev

可以看到systemd-tmpfiles-setup.service中的ExecStart正是我们要执行的命令,通过执行systemctl start systemd-tmpfiles-setup.service看下结果

[root@06b0e1e15b1b systemd]# systemctl start systemd-tmpfiles-setup.service
Failed to start systemd-tmpfiles-setup.service: Unit is masked.
[root@06b0e1e15b1b systemd]# systemctl unmask systemd-tmpfiles-setup.service
Removed symlink /etc/systemd/system/systemd-tmpfiles-setup.service.
[root@06b0e1e15b1b systemd]# systemctl start systemd-tmpfiles-setup.service

会发现报Unit is masked,执行ummask后发现服务可以正常start,再次重起发现问题解决。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐