我在CentOS7/8+PostgreSQL12上创建了一个用于SQL练习的Docker容器镜像
这是在CentOS7/8上创建PostgreSQL12的Docker镜像的步骤记录。(由于尝试创建Docker镜像时遇到了比预期更多的困难和试错,所以我将其作为备忘录发布出来。)
经过
半年不参与后端开发工作后,我忘记了很多东西(汗)…为了复习,我决定创建一个能进行SQL、数据库构建和设置实验操作的环境。要理解SQL操作和PostgreSQL的构建和设置,网络上有很多很棒的环境可供使用,但出于以下原因,我特意决定在Docker容器上创建可运行的PostgreSQL容器和镜像。
-
- コンテナ(Docker)操作の復習がしたい。
-
- 後日、コンテナ間でのデータベースのマルチクラスタ環境構築を試してみたいと考えていて、いつでも簡単に構築できるようにイメージ化しておきたい。
- ホストOS環境を汚したくない。
本次的目标
![スクリーンショット 2020-01-30 午前6.12.27.png](https://cdn.silicloud.com/blog-img/blog/img/657d49f337434c4406cb1699/5-0.png)
从安装了PostgreSQL服务器的CentOS容器映像中生成容器,并启动PostgreSQL服务器。使用主机操作系统上的客户端软件输入SQL,以便可以更新容器内的PostgreSQL服务器上的数据库。
在本次构建中不考虑以下因素。
-
- コンテナ間の接続はしない。
今後マルチクラスタ環境の構築を実現するために、コンテナ間のネットワークも考慮する必要はある。しかし、今回は設定せず、ホストOSのみからネットワーク経由でコンテナOSにSQLを要求するようにする。
セキュリティやアクセス制御
同一PCとはいえ、セキュリティやアクセス制御は設定することが望ましい。しかし、今回はSQL、データベースサーバ内部の学び用環境なので考慮しない。
データの永続化
DBデータ永続のためにホストOS上のディレクトリを共有化(マウント化)することも可能だが、今回は考慮しない。
Docker镜像创建环境
这次的环境设置如下:
主机操作系统选择了MacOS,容器操作系统选择了CentOS。
-
- ホストOS: Mac v10.15.2
-
- Docker Engine: v19.03.5
-
- コンテナOS:(CentOSはVer7とVer8の両方を試してみました。)
CentOS-7 v7.7.1908 (ベースイメージ元は”centos:7″)
CentOS-8 v8.1.1911 (ベースイメージ元は”centos:8″)
PostgreSQL: v12.1 (構築時のタイミングでは、CentOS標準リポジトリにver12がないようだったので、PostgreSQL標準リポジトリから取得することにしました。)
将Docker映像素材化的方法。
在中文中可以这样表达:关于形象化手段,可以考虑以下两种方法。
-
- 方法1 Commitによるイメージ生成
ベースとなるイメージからコンテナを生成起動し、コンテナ上で手動によりインストール・設定を行った状態のものをイメージ化する。
方法2 DOCKERFILEによるイメージ生成
ベースとなるイメージを基にして、インストール・設定手順をDOCKERFILEにより記述し、イメージ化する。
建议不要通过终端手动安装容器,而是遵循代码即基础设施的原则,考虑到配置和设置的明确化以及可重用性,
因个人习惯,请通过方法2来实现镜像化的目标。
在进行之前的准备时,基于以下原因,我们决定先进行方法1,然后再实施方法2。
-
- コンテナ上で正常に動作するのか、Dockerfileにどのような順番で書けば実現できるかわからず、確認したかったこと
- 方法2のために既存イメージから設定ファイルの取得が必要。
方法1:使用Commit来生成图像。
我们将按照以下的步骤进行图像化。
1-1. 下载Cent OS镜像,生成容器
1-2. 下载和安装PostgreSQL标准仓库包
1-3. 安装PostgreSQL服务器及其周边组件
1-4. 初始化数据库
1-5. 启动数据库服务器
1-6. 修改PostgreSQL的配置
1-7. 进行操作确认
1-8. 确认从主机操作系统的连接
1-9. 将容器镜像制作成镜像版本
1-10. 验证创建的镜像的可运行性
在安装CentOS上的PostgreSQL的步骤中,我参考了以下文章。
要在CentOS上安装PostgreSQL,可以参考以下步骤。
1-1. 下载CentOS镜像,并创建容器。
打开终端,使用”docker container run”命令下载基础镜像并生成容器。
CentOS-8のイメージを使う場合
$ docker container run -d --privileged -v (ホストOS内のディレクトリ):(コンテナOS内のディレクトリ) -p 10864:5432 --name='method1_cp12' centos:8 /sbin/init
CentOS-7のイメージを使う場合
$ docker container run -d --privileged -v (ホストOS内のディレクトリ):(コンテナOS内のディレクトリ) -p 10864:5432 --name='method1_cp12' centos:7 /sbin/init
為了確認作業的目的使用的SQL文件以及方法2所需要的,在容器內部創建和修改設定文件,我們使用了”-v”參數以便在主機和容器之間進行共享。這次我們試著在以下位置進行了設定。
-
- ホストOS側ディレクトリ:/Users/(ユーザ名)/sampleDocker/work/shared_directory
- コンテナOS側ディレクトリ:/var/shared_directory
另外,在CentOS容器中无法使用systemctl命令。为了在容器中使用,可以在”docker container run”的选项中添加”–privileged”参数来使用。本次使用它来自动启动和检查PostgreSQL服务,以及在”1-4.数据库服务器初始化”中的初始化shell脚本中执行systemctl命令,所以需要在容器中执行Systemctl命令。
(參考) 在 CentOS7 的 Docker 容器中啟用 systemctl
为了在容器内进行操作,请执行以下命令并进入容器。
$ docker container exec -it method1_cp12 /bin/bash
1-2. 下载并安装PostgreSQL的标准仓库包。
既然有这个机会…在CentOS-8上,我决定使用dnf命令进行安装。
CentOS-8の場合
# dnf -y install https://download.postgresql.org/pub/repos/yum/reporpms/EL-8-x86_64/pgdg-redhat-repo-latest.noarch.rpm
# dnf -qy module disable postgresql
CentOS-7の場合
# yum -y install https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm
1-3. 安装PostgreSQL服务器(及其周边设备)。
我要安装PostgreSQL。在之后的操作中,需要创建用户密码,但是因为CentOS中没有安装”passwd”,所以我需要进行安装。
CentOS-8の場合
# dnf -y install postgresql12-server postgresql12 postgresql12-contrib
# dnf -y install passwd
CentOS-7の場合
# yum -y install postgresql12-server postgresql12 postgresql12-contrib
# yum -y install passwd
1-4. 数据库的初始化
进行数据库的初始化。
# PGSETUP_INITDB_OPTIONS="-E UTF8 --no-locale" /usr/pgsql-12/bin/postgresql-12-setup initdb
1-5. 数据库服务器启动
启动PostgreSQL服务。
# systemctl start postgresql-12.service
我将检查服务是否正常工作。
# systemctl status postgresql-12.service
执行后,如果“postgresql-12.service”的活动状态显示为“active(running)”则表示正常。
1-6. 更改PostgreSQL的设置
请将设置更改为SQL客户端软件可以从主机操作系统访问。
另外,为了创建映像,在方法二中将配置文件和脚本复制到主机操作系统上。(请注意,此处说明的设置仅用于实验目的,并未考虑安全性。请根据使用目的和建立环境进行个人调整。)
使用文本编辑器(在此示例中使用vi),打开/var/lib/pgsql/12/data/postgresql.conf文件。
# vi /var/lib/pgsql/12/data/postgresql.conf
我們尋找「listen_addresses =」這一行,然後進行以下的修改。
-
- #listen_address = ‘localhost’のコメント部分(#)を消す。
-
- #port = 5432のコメント部分(#)を消す。
listen_address = ‘localhost’の’localhost’を’*’に変更。
/var/lib/pgsql/12/data/postgresql.conf
[変更前]
# – Connection Settings –
#listen_addresses = ‘localhost’ # what IP address(es) to listen on;
# comma-separated list of addresses;
# defaults to ‘localhost’; use ‘*’ for all
# (change requires restart)
#port = 5432 # (change requires restart)
max_connections = 100 # (change requires restart)
[変更後]
# – Connection Settings –
listen_addresses = ‘*’ # what IP address(es) to listen on;
# comma-separated list of addresses;
# defaults to ‘localhost’; use ‘*’ for all
# (change requires restart)
port = 5432 # (change requires restart)
max_connections = 100 # (change requires restart)
保存postgresql.conf文件并退出文本编辑器。
(通过上述设置将listen_addresses配置为’*’,可以接收任何连接,但由于这是用于实验,所以选择了这个设置。)
使用文本编辑器打开/var/lib/pgsql/12/data/pg_hba.conf。
# vi /var/lib/pgsql/12/data/pg_hba.conf
我要添加以下一行:
“host all all 0.0.0.0/0 md5”
</var/lib/pgsql/12/data/pg_hba.conf>
[変更前]
# "local" is for Unix domain socket connections only
local all all peer
# IPv4 local connections:
host all all 127.0.0.1/32 ident
# IPv6 local connections:
host all all ::1/128 ident
[変更後]
# "local" is for Unix domain socket connections only
local all all peer
# IPv4 local connections:
host all all 127.0.0.1/32 ident
host all all 0.0.0.0/0 md5
# IPv6 local connections:
host all all ::1/128 ident
保存pg_hba.conf文件并退出文本编辑器。
设置postgres用户的密码。
postgres用户既注册为操作系统用户,也注册为PostgreSQL用户,
因此需要进行两种密码的注册,以便从外部都能够访问。
(在此示例中,将默认用户’postgres’的密码注册为’postgres’。)
在第二个步骤中,由于需要在图像生成时执行相同的命令,因此需要进行脚本化,并更改PostgreSQL用户的设置。
准备两个shell脚本,命名如下:
– setting_postgresql.sh
– setting_postgresqluser.sh
新建一个名为“setting_postgresql.sh”的文件。
# vi /var/lib/pgsql/setting_postgresql.sh
将”setting_postgresql.sh”文件的内容如下所示进行编写并保存,然后关闭文本编辑器。
#!/bin/bash
echo 'postgres' | passwd --stdin postgres
su -l postgres -c "./setting_postgresqluser.sh"
创建新的”setting_postgresqluser.sh”文件。
# vi /var/lib/pgsql/setting_postgresqluser.sh
将”setting_postgresqluser.sh”文件的内容如下所示进行保存,并关闭文本编辑器。
#!/bin/bash
psql -c "ALTER ROLE postgres WITH password 'postgres'"
设置两个shell脚本的执行权限。
# chmod +x /var/lib/pgsql/setting_postgresql.sh
# chmod +x /var/lib/pgsql/setting_postgresqluser.sh
执行以下操作,这样可以为用户”postgres”注册密码。
# /var/lib/pgsql/setting_postgresql.sh
为了在方法2中进行后续操作,这次更改的配置文件和创建的shell脚本将保存在1-1中创建的共享目录(/var/shared_directory)中。
# cp /var/lib/pgsql/12/data/postgresql.conf /var/shared_directory/
# cp /var/lib/pgsql/12/data/pg_hba.conf /var/shared_directory/
# cp /var/lib/pgsql/setting_postgresql.sh /var/shared_directory/
# cp /var/lib/pgsql/setting_postgresqluser.sh /var/shared_directory/
另外,在执行方法2之前,需要先修改以下文件,因此将其复制。
# cp /usr/pgsql-12/bin/postgresql-12-setup /var/shared_directory/
在容器启动时,将注册设置为自动启动(持续运行)PostgreSQL服务。
# systemctl enable postgresql-12.service
为了反映之前的设置,我们将重新启动。
# systemctl restart postgresql-12.service
1-7. Action confirmation
1. 行动确认
2. 动作确认
3. 确认行动
4. 确认动作
5. 确认活动
6. 行为确认
7. 动作验证
为了确认操作,我们将进行一项操作确认。
为了确认数据库服务器的操作,我们尝试创建一个包含表格和插入数据的SQL文件。
# vi /var/shared_directory/sampleSQL.sql
在SQL文件中写下以下内容,并保存。关闭文本编辑器。
sql:/var/shared_directory/sampleSQL.sql
CREATE TABLE 果物 (
ID INTEGER PRIMARY KEY,
名前 VARCHAR(40) UNIQUE
);
CREATE TABLE 果物売買取引 (
取引ID SERIAL PRIMARY KEY,
取引日付 DATE,
果物ID INTEGER REFERENCES 果物(ID),
メモ VARCHAR(100) DEFAULT '不明',
買取額 INTEGER DEFAULT 0 CHECK(買取額>= 0),
売却額 INTEGER DEFAULT 0 CHECK(売却額>= 0),
個数 INTEGER DEFAULT 0 CHECK(個数>= 0)
);
INSERT INTO 果物(ID, 名前)
VALUES (0, 'オレンジ');
INSERT INTO 果物(ID, 名前)
VALUES (1, 'アップル');
INSERT INTO 果物(ID, 名前)
VALUES (2, 'バナナ');
INSERT INTO 果物売買取引(取引日付, 果物ID, 買取額, 個数)
VALUES ('2018-04-02', 1, 1200, 10);
INSERT INTO 果物売買取引(取引日付, 果物ID, 買取額, 個数)
VALUES ('2018-04-05', 2, 1500, 6);
INSERT INTO 果物売買取引(取引日付, 果物ID, 買取額, 個数)
VALUES ('2018-04-06', 0, 2000, 8);
执行SQL文件。
# su - postgres
$ cd /var/shared_directory/
$ psql -f ./sampleSQL.sql
我们会确认表格和插入的数据。
$ psql -d postgres -c "select * from 果物売買取引"
当数据已确认无误后,将注销”postgres”用户。
$ logout
由于处于容器登录状态,我暂时退出。
# exit
1-8. 从主操作系统确认连接
我们将从主机端进行连接确认。虽然可以在主机端安装psql,但这次我使用TablePlus作为客户端软件进行确认。
TablePlus的设置大致如此。
![image.png](https://cdn.silicloud.com/blog-img/blog/img/657d49f337434c4406cb1699/97-0.png)
完成后,您只需连接并确认之前创建的表是否可以进行SQL操作即可。
1-9. 将容器图像化
使用docker容器提交命令`docker container commit`可以创建正在运行的容器的Docker镜像。选项-a表示创建者,-c表示容器内部端口号(当执行docker container run命令时没有指定端口时适用)。最后输入镜像名称。例如,”gomadofu/method1_cp12:1″中,”gomadofu/method1_cp12″是镜像名称,”1″是标签。
$ docker container commit -a "GOMA DOFU" -c "EXPOSE 5432" -p method1_cp12 gomadofu/method1_cp12:1
1-10. 确认所创建图像的动作是否正常。
停止之前一直在运行的容器。
$ docker container stop method1_cp12
使用创建的“gomadofu/method1_cp12:1”镜像来生成和启动容器。
$ docker container run -d --privileged -v (ホストOS内のディレクトリ):(コンテナOS内のディレクトリ) -p 10864:5432 --name='method1_cp12_2' gomadofu/method1_cp12:1 /sbin/init
重新执行“1-8.从主机操作系统确认连接”的步骤。如果确认可以连接,则表示已完成。
一応,通过完成到这一步的工作,我们可以将CentOS和PostgreSQL进行容器化,并确认了其简单的运行情况。此外,我们还准备了方法2所需的配置文件和脚本。
第二种方法是通过DOCKERFILE生成镜像。
我們將按照以下步驟來創建圖片。
2-1. 准备图像构建目录
2-2. 创建DOCKERFILE文件
2-3. 修改initdb脚本
2-4. 执行构建
2-5. 启动容器(进行操作确认)
在这次的制作过程中,令人头疼的问题是”systemctl”命令的存在。
在方法一中,我们通过在容器启动时执行”–privileged”命令来在容器内使用它。然而,即使在Dockerfile中写入”systemctl”命令,构建时仍然会发生错误。
创建两个映像的方法可以在dockerfile内使用systemctl命令(确切地说是”systemctl enable”)来避免这个问题。
(仅供参考)请查看以下链接:https://hub.docker.com/_/centos?tab=description
尽管不使用 “systemctl” 命令也可以启动、关闭和重启服务,但为了在容器启动时自动启动PostgreSQL服务,我打算创建两个镜像以便使用”systemctl enable”命令。
另外,在“方法1的1-4.数据库初始化”中执行的“postgresql-12-setup”脚本中,使用了systemctl show命令,导致在构建时出现错误。因此,在“2-3.initdb脚本的修正”中需要修改脚本内容。
2-1. 准备用于图像构建的目录
![スクリーンショット 2020-01-30 午前11.50.57.png](https://cdn.silicloud.com/blog-img/blog/img/657d49f337434c4406cb1699/118-0.png)
由于需要为每个图像准备一个目录,所以这次我将准备两个目录。
-
- CentOS_Systemd ディレクトリ(イメージ名:”gomadofu/method2_csystemd”)
“systemctl”コマンドが使えるCentOSイメージを構成するDockerfileを格納するディレクトリです。
CentOS_Postgresql12 ディレクトリ(イメージ名:”gomadofu/method2_cp12”)
PostgreSQLインストール・設定済みのCentOSイメージを構成するDockerfileを格納するディレクトリです。
このディレクトリには方法1の過程で得られた、設定ファイル、スクリプトを格納します。
postgresql.conf
pg_hba.conf
setting_postgresql.sh
setting_postgresqluser.sh
Postgresql-12-setup
2-2.创建Dockerfile
我将创建一个DOCKERFILE。
DOCKERFILE的镜像支持systemctl命令。
在CentOS_Systemd目录中创建一个Dockerfile。
$ cd ./CentOS_Systemd
$ vi ./Dockerfile
请将以下内容写入Dockerfile并保存。
FROM centos:8
#centos:7を使う場合は "FROM centos:7”にする。
ENV container docker
RUN (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; done); \
rm -f /lib/systemd/system/multi-user.target.wants/*;\
rm -f /etc/systemd/system/*.wants/*;\
rm -f /lib/systemd/system/local-fs.target.wants/*; \
rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*;\
rm -f /lib/systemd/system/anaconda.target.wants/*;
VOLUME [ "/sys/fs/cgroup" ]
CMD ["/usr/sbin/init"]
PostgreSQL镜像的DOCKERFILE
在CentOS_Postgresql12目录中创建Dockerfile。
$ cd ../CentOS_Postgresql12
$ vi ./Dockerfile
将以下内容记录并保存到Dockerfile中。
FROM gomadofu/method2_csystemd:1
#CentOS-8の場合は以下を使う。
RUN dnf -y install https://download.postgresql.org/pub/repos/yum/reporpms/EL-8-x86_64/pgdg-redhat-repo-latest.noarch.rpm; \
dnf -qy module disable postgresql; \
dnf -y install postgresql12-server postgresql12 postgresql12-contrib; \
dnf -y install passwd;
#CentOS-7の場合は以下を使う。
# RUN yum -y install https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm; \
# yum -y install postgresql12-server postgresql12 postgresql12-contrib; \
# yum -y install passwd;
COPY ./postgresql-12-setup /usr/pgsql-12/bin/postgresql-12-setup
RUN chmod +x /usr/pgsql-12/bin/postgresql-12-setup
RUN PGSETUP_INITDB_OPTIONS="-E UTF8 --no-locale" /usr/pgsql-12/bin/postgresql-12-setup initdb
COPY ./*.conf /var/lib/pgsql/12/data/
COPY ./setting_*.sh /var/lib/pgsql/
RUN chmod +x /var/lib/pgsql/setting_postgres*.sh; \
chown -v postgres.postgres /var/lib/pgsql/12/data/postgresql.conf; \
chown -v postgres.postgres /var/lib/pgsql/12/data/pg_hba.conf; \
/var/lib/pgsql/setting_postgresql.sh;
EXPOSE 5432
RUN su -l postgres -c "/usr/pgsql-12/bin/pg_ctl start"; \
su -l postgres -c "./setting_postgresqluser.sh"; \
su -l postgres -c "/usr/pgsql-12/bin/pg_ctl stop"; \
systemctl enable postgresql-12.service;
CMD [“/usr/sbin/init"]
对2-3.initdb脚本进行修正。
将./CentOS_Postgresql12/Postgresql-12-setup进行修改。
$ vi ./Postgresql-12-setup
修改以下部分并保存。
<Postgresql-12-setup>
[変更前]
PGDATA=`systemctl show -p Environment "${SERVICE_NAME}.service" |
sed 's/^Environment=//' | tr ' ' '\n' |
sed -n 's/^PGDATA=//p' | tail -n 1`
if [ x"$PGDATA" = x ]; then
echo "failed to find PGDATA setting in ${SERVICE_NAME}.service"
exit 1
fi
[変更後]
PGDATA="/var/lib/pgsql/12/data/"
#PGDATA=`systemctl show -p Environment "${SERVICE_NAME}.service" |
# sed 's/^Environment=//' | tr ' ' '\n' |
# sed -n 's/^PGDATA=//p' | tail -n 1`
#if [ x"$PGDATA" = x ]; then
# echo "failed to find PGDATA setting in ${SERVICE_NAME}.service"
# exit 1
#fi
2-4.执行构建
创建一个支持systemctl命令的镜像。
$ cd ./CentOS_Systems
$ docker build --rm -t gomadofu/method2_csystemd:1 .
创建一个支持systemctl命令的镜像。
$ cd ../CentOS8_Postgresql12
$ docker build --rm -t gomadofu/method2_cp12:1 .
2-5. 启动容器(进行操作确认)
使用创建的映像来启动容器。
$ docker container run -d --privileged -v (ホストOS内のディレクトリ):(コンテナOS内のディレクトリ) -p 10864:5432 --name='method2_cp12' gomadofu/method2_cp12:1 /sbin/init
通过”1-7.动作确认”和”1-8.从主机操作系统进行连接确认”进行操作和连接确认测试,如果能够连接成功,则表示完成。