我在CentOS7/8+PostgreSQL12上创建了一个用于SQL练习的Docker容器镜像

这是在CentOS7/8上创建PostgreSQL12的Docker镜像的步骤记录。(由于尝试创建Docker镜像时遇到了比预期更多的困难和试错,所以我将其作为备忘录发布出来。)

经过

半年不参与后端开发工作后,我忘记了很多东西(汗)…为了复习,我决定创建一个能进行SQL、数据库构建和设置实验操作的环境。要理解SQL操作和PostgreSQL的构建和设置,网络上有很多很棒的环境可供使用,但出于以下原因,我特意决定在Docker容器上创建可运行的PostgreSQL容器和镜像。

    • コンテナ(Docker)操作の復習がしたい。

 

    • 後日、コンテナ間でのデータベースのマルチクラスタ環境構築を試してみたいと考えていて、いつでも簡単に構築できるようにイメージ化しておきたい。

 

    ホストOS環境を汚したくない。

本次的目标

スクリーンショット 2020-01-30 午前6.12.27.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

完成后,您只需连接并确认之前创建的表是否可以进行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

由于需要为每个图像准备一个目录,所以这次我将准备两个目录。

    • 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.从主机操作系统进行连接确认”进行操作和连接确认测试,如果能够连接成功,则表示完成。

广告
将在 10 秒后关闭
bannerAds