ローカル環境にDockerイメージをプールするためのサーバを構築

gahag-0079139294 Virtual Infrastructure

Docker のコンテナイメージをローカル環境にプールするためのレジストリサーバを構築します。

※ここでは実際に設定、動作したものを掲載していますが、内容について保証するものではありません。流用される場合は各自の責任でお願いします。

構築する環境の要件等については 「ローカル環境にプールしたDockerイメージからコンテナを起動する仕組みを構築」 をご参照ください。

全体の構築作業は以下のとおりですが、今回は「① ローカル環境にDockerイメージをプールするためのサーバを構築」を実施します。

① ローカル環境にDockerイメージをプールするためのサーバを構築
ローカルプールからDockerイメージをダウンロードし、起動するためのサーバを構築

今回の構築範囲は下図のとおりです。

container-structure-step1

セキュリティ機能の無効化

検証環境ではセキュリティ機能の影響を気にしたくないため、いくつかの機能を無効化しておきます。(実施する場合は各自の責任でお願いします)

SELinux のアクセス制御無効

[root@registry ~]# cp /etc/selinux/config /tmp
[root@registry ~]# vi /etc/selinux/config
[root@registry ~]# diff /tmp/config /etc/selinux/config
7c7
< SELINUX=enforcing
---
> SELINUX=permissive

Firewall 停止

[root@registry ~]# systemctl stop firewalld
[root@registry ~]# systemctl disable firewalld
Removed /etc/systemd/system/multi-user.target.wants/firewalld.service.
Removed /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.

ライブラリの最新化と必要なツールのインストール

パッケージ更新

OS にインストールされているパッケージを最新化しておきます。

[root@registry ~]# dnf update -y
  …
アップグレード済み:
  NetworkManager-1:1.40.16-15.el8_9.x86_64       NetworkManager-libnm-1:1.40.16-15.el8_9.x86_64    NetworkManager-team-1:1.40.16-15.el8_9.x86_64
  NetworkManager-tui-1:1.40.16-15.el8_9.x86_64   acl-2.2.53-3.el8.x86_64                           audit-3.1.2-1.el8.x86_64
  …
  xz-5.2.4-4.el8_6.x86_64                        xz-libs-5.2.4-4.el8_6.x86_64                      yum-4.7.0-20.el8.noarch
  zlib-1.2.11-26.el8.x86_64
インストール済み:
  glibc-gconv-extra-2.28-251.el8_10.4.x86_64     grub2-tools-efi-1:2.02-156.el8.rocky.0.1.x86_64   kernel-4.18.0-553.16.1.el8_10.x86_64   kernel-core-4.18.0-553.16.1.el8_10.x86_64
  kernel-modules-4.18.0-553.16.1.el8_10.x86_64   libevent-2.1.8-5.el8.x86_64                       libxkbcommon-0.9.1-1.el8.x86_64        pinentry-1.1.0-2.el8.x86_64
  python3-systemd-234-8.el8.x86_64               python3-unbound-1.16.2-5.el8_9.6.x86_64           unbound-libs-1.16.2-5.el8_9.6.x86_64   xkeyboard-config-2.28-1.el8.noarch

完了しました!

OS を再起動します。

[root@registry ~]# systemctl reboot

EPEL リポジトリインストール

Python 等、EPEL(Extra Packages for Enterprise Linux)からインストールするため、EPEL のリポジトリをインストールします。

[root@registry ~]# dnf install epel-release -y
…
インストール済み:
  epel-release-8-18.el8.noarch

完了しました!

jq インストール

JSON 形式のテキスト編集用のツールです。本環境ではプールに登録したイメージの一覧を表示する際に使用します。

[root@registry ~]# dnf install jq -y
…
インストール済み:
  jq-1.6-9.el8_10.x86_64                          oniguruma-6.8.2-3.el8.x86_64

完了しました!

Python3 インストール

Ansible のインストール要件に Python3.9 以上が必要なためインストールします。

Python3.9 が未インストールであること確認します。(インストール済の場合、リポジトリ名の前に@が付きます。)

[root@registry ~]# dnf list | grep python39
python39.x86_64                         3.9.19-7.module+el8.10.0+1860+afcc1c71            appstream
…
python39-xmltodict.noarch               0.12.0-1.el8                                      epel

Python3.9 のパッケージの情報を確認します。

[root@registry ~]# dnf info python39
メタデータの期限切れの最終確認: 0:11:25 前の 2024年09月01日 11時30分33秒 に実施しました。
利用可能なパッケージ
名前         : python39
バージョン   : 3.9.19
リリース     : 7.module+el8.10.0+1860+afcc1c71
Arch         : x86_64
サイズ       : 34 k
ソース       : python39-3.9.19-7.module+el8.10.0+1860+afcc1c71.src.rpm
リポジトリー : appstream
概要         : Version 3.9 of the Python interpreter
URL          : https://www.python.org/
ライセンス   : Python
説明         : Python 3.9 is an accessible, high-level, dynamically typed, interpreted
…

Python3.9 をインストールします。

[root@registry ~]# dnf install python39 -y
…
インストール済み:
  python39-3.9.19-7.module+el8.10.0+1860+afcc1c71.x86_64                       python39-libs-3.9.19-7.module+el8.10.0+1860+afcc1c71.x86_64
  python39-pip-20.2.4-9.module+el8.10.0+1860+afcc1c71.noarch                   python39-pip-wheel-20.2.4-9.module+el8.10.0+1860+afcc1c71.noarch
  python39-setuptools-50.3.2-6.module+el8.10.0+1861+0f5e39ec.noarch            python39-setuptools-wheel-50.3.2-6.module+el8.10.0+1861+0f5e39ec.noarch
  python39-tkinter-3.9.19-7.module+el8.10.0+1860+afcc1c71.x86_64

完了しました!

Python3 のバージョンを確認します。

[root@registry ~]# python3 -V
Python 3.9.19

[root@registry ~]# pip3 -V
pip 20.2.4 from /usr/lib/python3.9/site-packages/pip (python 3.9)

pip を最新化しておきます。(pip は Python のパッケージ管理システムです)

[root@registry ~]# python3 -m pip install pip --upgrade
WARNING: Running pip install with root privileges is generally not a good idea. Try `python3 -m pip install --user` instead.
Collecting pip
  Downloading pip-24.2-py3-none-any.whl (1.8 MB)
     |????????????????????????????????| 1.8 MB 2.7 MB/s
Installing collected packages: pip
Successfully installed pip-24.2

[root@registry ~]# pip3 -V
pip 24.2 from /usr/local/lib/python3.9/site-packages/pip (python 3.9)

Ansible インストール

本環境では Ansible のインストールは pip で行います。対象モジュールを個別にインストールすることもできますが、ここではモジュール名のリストを作成し、pip でまとめてインストールします。

インストール対象のモジュール名(Ansible 等)を requirements.txt に登録します。

[root@registry ~]# vi requirements.txt
[root@registry ~]# cat requirements.txt
ansible
ansible-core
Jinja2
requests

モジュールを pip でインストールします。

[root@registry ~]# python3 -m pip install -r requirements.txt
…
Successfully installed Jinja2-3.1.4 MarkupSafe-2.1.5 PyYAML-6.0.2 ansible-8.7.0 ansible-core-2.15.12 certifi-2024.8.30 cffi-1.17.0 charset-normalizer-3.3.2 cryptography-43.0.1 idna-3.8 importlib-resources-5.0.7 packaging-24.1 pycparser-2.22 requests-2.32.3 resolvelib-1.0.1 urllib3-2.2.2
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager, possibly rendering your system unusable.It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv. Use the --root-user-action option if you know what you are doing and want to suppress this warning.

インストールした Ansible のバージョンを確認します。

[root@registry ~]# ansible --version
ansible [core 2.15.12]
  config file = None
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/local/lib/python3.9/site-packages/ansible
  ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/local/bin/ansible
  python version = 3.9.19 (main, Aug 29 2024, 05:41:50) [GCC 8.5.0 20210514 (Red Hat 8.5.0-22)] (/usr/bin/python3)
  jinja version = 3.1.4
  libyaml = True

Ansible のコレクションをインストールします。コレクションはモジュール等をパッケージ化したものです。

インストール対象のコレクション名を requirements.yml に登録します。

[root@registry ~]# vi requirements.yml
[root@registry ~]# cat requirements.yml
---
collections:
- name: community.general
  source: https://galaxy.ansible.com
- name: community.docker
  source: https://galaxy.ansible.com
- name: ansible.posix
  source: https://galaxy.ansible.com

コレクションをインストールします。

[root@registry ~]# ansible-galaxy collection install -r requirements.yml
Starting galaxy collection install process
Nothing to do. All requested collections are already installed. If you want to reinstall them, consider using `--force`.

Docker インストール

Docker のリポジトリをインストールするためのツールをインストールします。

[root@registry ~]# dnf install yum-utils -y
…
インストール済み:
  yum-utils-4.0.21-25.el8.noarch

完了しました!

Docker のリポジトリをインストールします。

[root@registry ~]# yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
repo の追加: https://download.docker.com/linux/centos/docker-ce.repo

Docker をインストールします。

[root@registry ~]# yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y
…
インストール済み:
  container-selinux-2:2.229.0-2.module+el8.10.0+1843+6892ab28.noarch            containerd.io-1.6.32-3.1.el8.x86_64
  docker-buildx-plugin-0.14.0-1.el8.x86_64                                      docker-ce-3:26.1.3-1.el8.x86_64
  docker-ce-cli-1:26.1.3-1.el8.x86_64                                           docker-ce-rootless-extras-26.1.3-1.el8.x86_64
  docker-compose-plugin-2.27.0-1.el8.x86_64                                     fuse-common-3.3.0-19.el8.x86_64
  fuse-overlayfs-1.13-1.module+el8.10.0+1843+6892ab28.x86_64                    fuse3-3.3.0-19.el8.x86_64
  fuse3-libs-3.3.0-19.el8.x86_64                                                libcgroup-0.41-19.el8.x86_64
  libslirp-4.4.0-2.module+el8.10.0+1843+6892ab28.x86_64                         slirp4netns-1.2.3-1.module+el8.10.0+1843+6892ab28.x86_64
  tar-2:1.30-9.el8.x86_64

完了しました!

Docker の起動状況を確認します。(→ Docker の自動起動は disabled、現在は inactive(停止中))

[root@registry ~]# systemctl is-enabled docker; systemctl is-active docker
disabled
inactive

Docker の自動起動を enable とし、即時起動します。

[root@registry ~]# systemctl enable docker --now
Created symlink /etc/systemd/system/multi-user.target.wants/docker.service → /usr/lib/systemd/system/docker.service.

Docker が起動していることを確認します。

[root@registry ~]# systemctl status docker
● docker.service - Docker Application Container Engine
   Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
   Active: active (running) since Wed 2024-09-01 13:35:40 JST; 35s ago
     Docs: https://docs.docker.com
 Main PID: 8503 (dockerd)
    Tasks: 8
   Memory: 39.7M
   CGroup: /system.slice/docker.service
           └8503 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

 9月 01 13:35:39 registry systemd[1]: Starting Docker Application Container Engine...
 9月 01 13:35:39 registry dockerd[8503]: time="2024-09-01T13:35:39.343521801+09:00" level=info msg="Starting up"
 9月 01 13:35:39 registry dockerd[8503]: time="2024-09-01T13:35:39.406922385+09:00" level=info msg="Loading containers: start."
 9月 01 13:35:40 registry dockerd[8503]: time="2024-09-01T13:35:40.077493387+09:00" level=info msg="Loading containers: done."
 9月 01 13:35:40 registry dockerd[8503]: time="2024-09-01T13:35:40.098389387+09:00" level=info msg="Docker daemon" commit=8e96db1 containerd-snapshotter=false stora>
 9月 01 13:35:40 registry dockerd[8503]: time="2024-09-01T13:35:40.098597754+09:00" level=info msg="Daemon has completed initialization"
 9月 01 13:35:40 registry dockerd[8503]: time="2024-09-01T13:35:40.163326594+09:00" level=info msg="API listen on /run/docker.sock"
 9月 01 13:35:40 registry systemd[1]: Started Docker Application Container Engine.

SSH 用キーの配置

のちほど起動するコンテナの OS(linux)のカスタマイズ(アプリのインストール等)は Ansible で自動化します。カスタマイズ時、Ansible はコンテナの OS に SSH公開鍵認証で接続します。

レジストリサーバに鍵が作成されていない場合は ssh-keygen コマンドで作成してください。
以下のファイル(id_rsa:秘密鍵、id_rsa.pub:公開鍵)は root アカウントで ssh-keygen コマンドを実行し作成したときの鍵です。コマンド実行時のパラメータ指定は全てデフォルト(未指定)です。また、アクセス権を緩めると SSH 接続時に失敗する可能性がありますのでご注意ください。

[root@registry ~]# ls -la ~/.ssh
合計 8
drwx------. 2 root root   38  9月  4 13:23 .
dr-xr-x---. 5 root root  225  9月  4 13:14 ..
-rw-------. 1 root root 3247  6月 18 14:16 id_rsa
-rw-r--r--. 1 root root  742  6月 18 14:16 id_rsa.pub

プール作成

registry コンテナはプールした Docker イメージをコンテナ内の /var/lib/registry 配下に保存します。そのため、registry コンテナを削除するとプールしたイメージも消えてしまいます。Docker ではコンテナのディレクトリを外部ディスクにマウントすることで、コンテナ削除後もデータを残すことが可能です。本設定では registry コンテナ内の /var/lib/registry をコンテナのホストであるレジストリサーバのディスクにマウントします。

レジストリサーバにマウント先のディレクトリを作成します。

[root@registry ~]# mkdir /registry
[root@registry ~]#

以下のコマンドで registry イメージからコンテナを起動します。registry イメージがレジストリサーバに存在しない場合、先に registry イメージが Docker HUB からダウンロードされます。-v のオプションで registry コンテナ内の /var/lib/registry をレジストリサーバの /registry にマウントしています。

[root@registry ~]# docker run -d -p 5000:5000 -v /registry:/var/lib/registry --name registry registry:2
Unable to find image 'registry:2' locally
2: Pulling from library/registry
930bdd4d222e: Pull complete
a15309931e05: Pull complete
6263fb9c821f: Pull complete
86c1d3af3872: Pull complete
a37b1bf6a96f: Pull complete
Digest: sha256:12120425f07de11a1b899e418d4b0ea174c8d4d572d45bdb640f93bc7ca06a3d
Status: Downloaded newer image for registry:2
a72f7529596adb78eebcbaa97b0e3e92e1773db0fc86ee10e14d97baeec694fd

レジストリサーバにダウンロードされている registry イメージを確認します。

[root@registry ~]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
registry     2         cfb4d9904335   11 months ago   25.4MB

registry コンテナの起動状況を確認します。

[root@registry ~]# docker ps
CONTAINER ID   IMAGE        COMMAND                   CREATED          STATUS          PORTS                                       NAMES
a72f7529596a   registry:2   "/entrypoint.sh /etc…"   30 seconds ago   Up 28 seconds   0.0.0.0:5000->5000/tcp, :::5000->5000/tcp   registry

プールにイメージを登録

プールに登録するイメージを作成

本環境では2つのイメージを作成しプールします。(下表参照)

名前ベースとなるイメージ (*1)インストールするアプリ役割
r8bindrockylinux:8.8BINDDNS Server
r8stubrockylinux:8.8dnsperf、kdig 等Client

ベースとなるイメージのダウンロードと OS の最低限の設定 (*2) についての手続きは Dockerfile に定義します。アプリのインストールおよびコンフィグ設定は Ansible で自動化します。

*1 Docker HUB から自動的にダウンロードされます。
*2 基本ツールのインストール、アカウント設定、SSH接続設定など。

イメージ作成のおおまかな流れは以下のとおりです。

  1. Dockerfile の定義に基づきコンテナの起動と最低限の設定を行う (*3)
  2. Ansible でコンテナをカスタマイズ(アプリのインストール等)する
  3. カスタマイズ済みのコンテナからイメージを作成する

*3 本設定では docker compose コマンドでコンテナを起動します。docker compose コマンドには YAML 形式の定義ファイルをオプションとして指定します。YAML ファイル内には Dockerfile のパスが指定されており、docker compose コマンドは間接的に Dockerfile を読み込みます。

以降の手順 (*4) では /home/docker をカレントディレクトリとして作業を行っています。(*5)

*4 ここでは Docker および Ansible の学習を目的としているわけではないため、仕様の細かい説明は行わない予定です。インターネット上に詳しい情報があると思いますのでそちらをご参照ください。

*5 docker アカウントを作成しているわけではありません。単に /home の下に docker ディレクトリを作成しているだけです。

docker compose コマンドで r8bind と r8stub のコンテナを起動します。(*6)

*6 コンテナの起動元のイメージがレジストリサーバに存在しない場合、先に Docker HUB からダウンロードされます。

[root@registry docker]# docker compose -f ./compose_bind.yml up -d
WARN[0000] /home/docker/compose_network.yml: `version` is obsolete
WARN[0000] /home/docker/compose_bind.yml: `version` is obsolete
…
 ? Network net01     Created                     0.2s
 ? Container r8bind  Started                     0.4s

[root@registry docker]# docker compose -f ./compose_mob.yml up -d
WARN[0000] /home/docker/compose_network.yml: `version` is obsolete
WARN[0000] /home/docker/compose_mob.yml: `version` is obsolete
…
 ? Container r8stub  Started                     0.5s

ダウンロードされたイメージを確認します。

[root@registry docker]# docker images
REPOSITORY              TAG       IMAGE ID       CREATED             SIZE
r8bind                  latest    1ea1463cf211   About an hour ago   1.06GB
r8stub                  latest    d2f47b50190b   About a minute ago  1.06GB
registry                2         cfb4d9904335   11 months ago       25.4MB

コンテナの起動状況を確認します。

[root@registry docker]# docker ps
CONTAINER ID   IMAGE        COMMAND                   CREATED              STATUS              PORTS                                       NAMES
f7d480dedbff   r8stub       "/sbin/init"              About a minute ago   Up About a minute   0.0.0.0:2220->22/tcp, :::2220->22/tcp       r8stub
cf22808e34f9   r8bind       "/sbin/init"              About an hour ago    Up About an hour    0.0.0.0:2210->22/tcp, :::2210->22/tcp       r8bind
a72f7529596a   registry:2   "/entrypoint.sh /etc…"   22 hours ago         Up 22 hours         0.0.0.0:5000->5000/tcp, :::5000->5000/tcp   registry

コンテナの起動は docker compose コマンドで行いますが、どのようなコンテナかは -f オプションに指定するYAML 形式のファイルで定義づけられます。本環境では、compose_bind.yml により r8bind(DNS Server)が、compose_mob.yml で r8stub(Client)が起動するように定義しています。ただし、compose_bind.yml と compose_mob.yml は同じ Dockerfile を使用しているため、起動するコンテナは IP アドレス、ホスト名等を除けばほぼ違いはありません。それぞれの固有の設定は、のちほど Ansible で行います。

コンテナ起動用に用意した定義ファイルを以下に示します。

ファイル (*7)内容
./compose_bind.ymlr8bind(DNS Server)起動用の定義ファイル
./compose_mob.ymlr8stub(Client)起動用の定義ファイル
./compose_network.ymlコンテナが接続する LAN の定義ファイル
./dockerfiles/rocky8/DockerfileRocky8 をベースとした OS の基本設定が定義されたファイル
./dockerfiles/rocky8/id_rsa
./dockerfiles/rocky8/id_rsa.pub
./dockerfiles/rocky9/DockerfileRocky9 をベースとした OS の基本設定が定義されたファイル (*8)
./dockerfiles/rocky9/id_rsa
./dockerfiles/rocky9/id_rsa.pub

*7 ファイルおよびディレクトリは /home/docker からの相対パスです。

*8 起動するコンテナ(r8bind、r8stub)はいづれも Rocky8 をベースとしているため、こちら(Rocky9用)の Dockerfile は本環境では使用していません。

compose_network.yml は docker compose コマンドの -f オプションで指定することはありませんが、compose_bind.yml と compose_mob.yml から include されているため、間接的に読み込まれます。compose_network.yml には、コンテナが接続する LAN(net01:172.18.1.0/24、net02:172.18.2.0/24)が定義されています。

id_rsa と id_rsa.pub はそれぞれ、SSH公開鍵認証で使用する秘密鍵と公開鍵です。のちほど Ansible でコンテナをカスタマイズする際、SSH公開鍵認証で接続します。そのため前述の「SSH 用キーの配置」でホストサーバ(レジストリサーバ)に配置したものと同じ鍵をコンテナにも配置する必要があります。Dockerfile には、これらの鍵をコンテナ OS 内の所定のディレクトリに配置するための手続きが定義されています。

各ファイルの内容について簡単に説明します。(compose_mob.yml の内容は、compose_bind.yml と同等のため説明は割愛させていただきます。)

compose_bind.yml
version: '3'                          << [1]

services:

  r8bind:
    image: r8bind                     <<イメージ化した際のイメージ名
    container_name: r8bind            <<コンテナ名
    hostname: r8bind                  <<コンテナで起動する OS のホスト名
    privileged: true
    build:
      context: ./dockerfiles/rocky8/  <<Dockerfile の配置場所
      dockerfile: Dockerfile          <<Dockerfile の名前
    …
    volumes:
      - /sys/fs/cgroup:/sys/fs/cgroup:ro
      - /home/docker/vol/r8bind:/home/docker/files:rw  << [2]
    …
    ports:
      - "2204:22"                     <<ポート指定 [3]
    networks:
      net01:
        ipv4_address: 172.18.1.4      <<コンテナOS へ割り当てられる IPアドレス
        ipv6_address: fd00::4
        priority: 1000

include:
  - ./compose_network.yml             <<LAN の定義ファイルを include [4]

[1] Docker Compose v2 以降は version: 指定は非推奨らしいです。docker compose コマンド実行時の警告メッセージは無視でかまいませんが、煩わしい場合はこの指定を削除(もしくはコメント化)してください。

[2] コンテナ OS の /home/docker/files を レジストリサーバの /home/docker/vol/r8bind にマウントしています。このディレクトリを介してコンテナ OS とレジストリサーバのデータの受け渡しが可能です。また、このディレクトリにデータを保存することで、コンテナ削除後もデータを残すことが可能です。

[3] ホスト OS とコンテナ OS のポートをつなぐための指定ですが、本設定では SSH ポート(22)を接続しています。外部からレジストリサーバの 2204 ポートへ接続すると、コンテナ OS の 22 ポートへ SSH 接続されます。

[4] コンテナが接続する LAN が定義されたファイルを include しています。include せずに compose_network.yml の内容をここに直接展開しても問題ありません。
compose_network.yml
version: '3'

networks:
  net01:
    name: net01                       <<ネットワーク名
    driver: bridge                    <<ブリッジネットワークの指定 [1]
    enable_ipv6: true                 <<IPv6 通信の有効化
    ipam:
      driver: default
      config:
        - subnet: "172.18.1.0/24"     <<サブネットの指定(IPv4)
          gateway: "172.18.1.1"       <<ゲートウェイの指定(IPv4)
        - subnet: "fd00::/64"         <<サブネットの指定(IPv6)
          gateway: "fd00::1"          <<ゲートウェイの指定(IPv6)
  net02:
    …

[1] 同じブリッジネットワークに接続するコンテナ間では通信が可能です。
Dockerfile
FROM rockylinux:8.8                   <<Docker HUB からダウンロードするイメージ
…

RUN dnf update -y                     <<パッケージ更新や基本ツールのインストール
RUN dnf install -y epel-release
…

ENV ssh_pub id_rsa.pub                <<SSH公開鍵認証のための設定
…

RUN echo ${root_password} | passwd --stdin root  <<root のパスワード設定

# disable DNS lookup
RUN sed s/.*UseDNS.*/"UseDNS no"/ -i /etc/ssh/sshd_config  <<SSH 用の設定

VOLUME [ "/sys/fs/cgroup" ]

#ENTRYPOINT ["/sbin/init"]
CMD ["/sbin/init"]                    <<開始プロセス [1]

[1] linux では最初のプロセスとして init を起動し、そこから OS に必要なプロセスを順次起動します。CMD に別のコマンドを指定した場合、そのコマンドで起動されるプロセス専用のコンテナとなります。
Docker コンテナは本来、機能特化した環境を作ることを目的としているようです。例えば、Web 専用、DNS 専用、のような感じです。単一機能に必要なアプリやライブラリ、リソースをコンテナに集約・独立させることで、ホスト OS や他のコンテナのアップデート等による影響を低減させています。
本環境のコンテナは、一般的な OS 起動と同じく init プロセスを最初に起動させます。

次に Ansible でコンテナのカスタマイズを行います。

対象コンテナが hosts に登録されていることを確認します。

[root@registry docker]# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
172.18.1.4  r8bind
172.18.1.30 r8stub

対象コンテナの SSH キーが known_hosts に登録済みの場合、Ansible が対象コンテナへ接続する際にエラーとなるため、予め削除しておきます。

[root@registry docker]# vi ~/.ssh/known_hosts

ansible-playbook コマンドで r8bind と r8stub のカスタマイズを実行します。

[root@registry docker]# ansible-playbook -i inventory.ini r8bind_main.yml

PLAY [r8bind] ********************************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************************
The authenticity of host 'r8bind (172.18.1.4)' can't be established.
ECDSA key fingerprint is SHA256:AE0HpbyDKGU2VntPAM25x/0owRxEss0iH0zBAFdE2K8.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes <yesを回答すると~/.ssh/known_hostsにキーが登録される
…
PLAY RECAP ***********************************************************************************************************************
r8bind                     : ok=14   changed=11   unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
[root@registry docker]# ansible-playbook -i inventory.ini r8stub_main.yml

PLAY [r8stub] ********************************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************************
The authenticity of host 'r8stub (172.18.1.30)' can't be established.
ECDSA key fingerprint is SHA256:J8y2zFOOhbXzSES86aWr2RaR7GZLijJMIOmosSUPfjs.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
…
PLAY RECAP ***********************************************************************************************************************
r8stub                     : ok=12   changed=6    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

カスタマイズは ansible-playbook コマンドで実行しますが、そのオプションにスクリプトファイルを指定します。r8bind のカスタマイズには r8bind_main.yml を、r8stub のカスタマイズには r8stub_main.yml を指定しています。

カスタマイズの内容が定義されているファイルを以下に示します。

ファイル (*9)内容
./inventory.ini 操作対象のノードのリスト
./r8bind_main.yml r8bind カスタマイズ用スクリプトの開始ファイル
./r8stub_main.yml r8stub カスタマイズ用スクリプトの開始ファイル
./group_vars/all.yml 環境変数が登録されたファイル
./roles/install_bind/ r8bind のカスタマイズに必要なファイルが置かれたディレクトリ
./roles/install_bind/files/com.zone BIND 用のコンフィグファイルとゾーンファイル
./roles/install_bind/files/jp.zone
./roles/install_bind/files/named.conf
./roles/install_bind/files/root.zone
./roles/install_bind/files/test.co.jp.zone
./roles/install_bind/files/test.com.zone
./roles/install_bind/handlers/main.yml notify イベントで起動するハンドラーが登録されているファイル
./roles/install_bind/tasks/install_bind.yml BIND をインストールするスクリプト
./roles/install_bind/tasks/main.yml install_bind.yml を呼び出すスクリプト
./roles/setup_os/ OS のカスタマイズに必要なファイルが置かれたディレクトリ
./roles/setup_os/tasks/main.yml setup_os.yml を呼び出すスクリプト
./roles/setup_os/tasks/setup_os.yml OS 共通設定用のスクリプト
./roles/setup_os/templates/gai.conf.j2 IPv4優先するコンフィグのテンプレート
./roles/setup_os/templates/resolv.conf.j2 resolv.conf のテンプレート(本設定では未使用)
./roles/setup_stub/ r8stub のカスタマイズに必要なファイルが置かれたディレクトリ
./roles/setup_stub/tasks/main.yml setup_stub.yml を呼び出すスクリプト
./roles/setup_stub/tasks/setup_stub.yml dnsperf 等のツールをインストールするスクリプト

*9 ファイルおよびディレクトリは /home/docker からの相対パスです。

r8bind_main.yml と r8stub_main.yml 以外のスクリプトはこれらのスクリプトから順次呼び出されます。以下にコーリングシーケンスを示します。

r8bind_main.yml
→./roles/setup_os/tasks/main.yml
  →./roles/setup_os/tasks/setup_os.yml
→./roles/install_bind/tasks/main.yml
  →./roles/install_bind/tasks/install_bind.yml

r8stub_main.yml
→./roles/setup_os/tasks/main.yml
  →./roles/setup_os/tasks/setup_os.yml
→./roles/setup_stub/tasks/main.yml
  →./roles/setup_stub/tasks/setup_stub.yml

各ファイルの内容について簡単に説明します。(一目瞭然のファイルについては割愛させていただきます。)

setup_os.yml
---

- name: set timezone to Asia/Tokyo            <<TimeZone設定
  become: true
  community.general.timezone:
    name: Asia/Tokyo

- name: prefer ipv4 over ipv6 on system wide  <<IPv4優先のコンフィグをテンプレートから作成し
  become: true                                <<コンテナ OS に配置
  ansible.builtin.template:
    src: gai.conf.j2
    dest: /etc/gai.conf
    owner: root
    group: root
    mode: 0644
    backup: yes
#  when: prefer_ipv4_over_v6_system_wide
install_bind.yml
---
- name: install bind               << dnf で BIND をインストール
  become: true
  ansible.builtin.dnf:
    name: "{{ item }}"
    state: present
  loop:
    - bind

- name: start bind                 <<systemd で named.service を起動
  become: true
  ansible.builtin.systemd:
    state: started
    name: "{{ item }}"
    enabled: true
  loop:
    - named.service

- name: copy named.conf and zone file   <<BIND のコンフィグ&ゾーンファイルを
  block:                                <<コンテナにコピー

  - name: copy named.conf
    become: true
    ansible.builtin.copy:
      src: named.conf
      dest: /etc/named.conf
      owner: root
      group: named
      mode: '0640'
      backup: yes

      …

  notify: reload named             <<named プロセスを再起動(ハンドラー起動)
setup_stub.yml
---
- name: install dnsperf and kdig     <<dnf で dnsperf と kdig(knot-utils)をインストール
  become: true
  ansible.builtin.dnf:
    name: "{{ item }}"
    state: present
  loop:
    - dnsperf
    - knot-utils

- name: preparate to install Metasploit      <<Metasploit をインストール
  become: true
  ansible.builtin.shell:
    cmd: "curl https://raw.githubusercontent.com/rapid7/metasploit-omnibus/master/config/templates/metasploit-framework-wrappers/msfupdate.erb > /tmp/msfinstall"
  register: result
- debug: msg="{{ result.stdout_lines }}"

  …

- name: install scapy                <<scapy をインストール
  become: true
  ansible.builtin.shell:
    cmd: "python3 -m pip install scapy"
  register: result
- debug: msg="{{ result.stdout_lines }}"

カスタマイズ後のコンテナでコマンド(uname -a と ps)を実行し、問題ないことを確認します。

[root@registry docker]# docker exec -it r8bind uname -a;ps
Linux r8bind 4.18.0-553.16.1.el8_10.x86_64 #1 SMP Thu Aug 8 17:47:08 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
    PID TTY          TIME CMD
  10137 pts/0    00:00:00 bash
  26309 pts/0    00:00:00 ps

[root@registry docker]# docker exec -it r8stub uname -a;ps
Linux r8stub 4.18.0-553.16.1.el8_10.x86_64 #1 SMP Thu Aug 8 17:47:08 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
    PID TTY          TIME CMD
  10137 pts/0    00:00:00 bash
  26332 pts/0    00:00:00 ps

カスタマイズ済みのコンテナからプール登録用のイメージを作成します。

[root@registry docker]# docker commit r8bind localhost:5000/r8bind
sha256:1ad1dad765ea4a2d4390938ff342b3aaaf0e030714500e21c09df8560673047c

[root@registry docker]# docker commit r8stub localhost:5000/r8stub
sha256:5eb1968e9c85ead86816404f2ac993c86f6633aa0756a3a0728150331d978a72

新たに作成したイメージを確認します。

[root@registry docker]# docker images
REPOSITORY              TAG       IMAGE ID       CREATED          SIZE
localhost:5000/r8stub   latest    5eb1968e9c85   38 seconds ago   2.13GB
localhost:5000/r8bind   latest    1ad1dad765ea   39 minutes ago   1.19GB
r8bind                  latest    1ea1463cf211   2 hours ago      1.06GB
r8stub                  latest    d2f47b50190b   2 hours ago      1.06GB
registry                2         cfb4d9904335   11 months ago    25.4MB

イメージをプールに登録

作成したイメージ(localhost:5000/r8bind, localhost:5000/r8stub)をプールに登録します。

[root@registry docker]# docker push localhost:5000/r8bind
…
121bf763d994: Pushed
964fc91a3863: Pushed
latest: digest: sha256:a19bb7ce8d3631fd8dc32540117046946d5357b9ad06d8cd1a991c9a3b062a6b size: 8074

[root@registry docker]# docker push localhost:5000/r8stub
…
121bf763d994: Mounted from r8bind
964fc91a3863: Mounted from r8bind
latest: digest: sha256:8357a1c13dc253e51fde284a3185dd0b08ba74d09c639c816bed1876d99eab8e size: 8075

プールに登録したイメージを確認します。

[root@registry docker]# curl -s http://localhost:5000/v2/_catalog | jq
{
  "repositories": [
    "r8bind",
    "r8stub"
  ]
}

不要なコンテナおよびイメージの削除

プールへの登録元のイメージおよびコンテナは不要となります。ディスク容量節約のため削除します。

コンテナを停止します。

[root@registry docker]# docker stop r8bind r8stub
r8bind
r8stub

コンテナを削除します。

[root@registry docker]# docker rm r8bind r8stub
r8bind
r8stub

イメージを削除します。

[root@registry docker]# docker rmi localhost:5000/r8stub localhost:5000/r8bind
Untagged: localhost:5000/r8stub:latest
Untagged: localhost:5000/r8stub@sha256:8357a1c13dc253e51fde284a3185dd0b08ba74d09c639c816bed1876d99eab8e
Deleted: sha256:5eb1968e9c85ead86816404f2ac993c86f6633aa0756a3a0728150331d978a72
Deleted: sha256:d8c54a9be9e1d8731bf8260de859075e1fcd87d6952570d9e2247487dd003d1a
Untagged: localhost:5000/r8bind:latest
Untagged: localhost:5000/r8bind@sha256:a19bb7ce8d3631fd8dc32540117046946d5357b9ad06d8cd1a991c9a3b062a6b
Deleted: sha256:1ad1dad765ea4a2d4390938ff342b3aaaf0e030714500e21c09df8560673047c
Deleted: sha256:fd569ad8a0073eb5ef7a7cc26cb1665e5bd79be390f37b81f198fc6625f65301

[root@registry docker]# docker rmi r8stub r8bind
Untagged: r8stub:latest
Deleted: sha256:d2f47b50190bcca11f1e83ad1e32170425a0365ccb299e5f732d7889ddd549a9
Untagged: r8bind:latest
Deleted: sha256:1ea1463cf2119337a210395d98793495d2ea267308ae880e6eed6d2703a2dabc

不要なオブジェクトを削除します。(コンテナ削除後、net01 ネットワークはどこからも参照されなくなるため削除対象となります)

[root@registry docker]# docker system prune
WARNING! This will remove:
  - all stopped containers
  - all networks not used by at least one container
  - all dangling images
  - unused build cache

Are you sure you want to continue? [y/N] y
Deleted Networks:
net01
…
Total reclaimed space: 862.9MB

プールに登録済みのイメージを削除

プールにイメージを再登録する場合は、事前に古いイメージをプールから削除する必要があります。手順について以下に示します。

registry コンテナを環境変数(REGISTRY_STORAGE_DELETE_ENABLED=true)付きで再起動します。

registry コンテナの起動状況を確認します。

[root@registry docker]# docker ps -f name=registry
CONTAINER ID   IMAGE        COMMAND                   CREATED      STATUS      PORTS                                       NAMES
a72f7529596a   registry:2   "/entrypoint.sh /etc…"   2 days ago   Up 2 days   0.0.0.0:5000->5000/tcp, :::5000->5000/tcp   registry

registry コンテナの停止と削除。

[root@registry docker]# docker stop registry
registry

[root@registry docker]# docker rm registry
registry

registry コンテナを再起動します。

[root@registry docker]# docker run -d -p 5000:5000 -e REGISTRY_STORAGE_DELETE_ENABLED=true -v /registry:/var/lib/registry --name registry registry:2
8c045932271502a6f1006c64ac89eb1cfac45bbfcc104f94b71bfebdd50e2233

プールに登録済みのイメージを確認します。(以降の手順で r8bind を削除します)

[root@registry docker]# curl -s http://localhost:5000/v2/_catalog | jq
{
  "repositories": [
    "r8bind",
    "r8stub"
  ]
}

r8bind イメージのダイジェストを確認します。

[root@registry docker]# curl -i -H "Accept: application/vnd.docker.distribution.manifest.v2+json" http://localhost:5000/v2/r8bind/manifests/latest | grep Docker-Content-Digest
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  8074  100  8074    0     0   606k      0 --:--:-- --:--:-- --:--:--  606k
Docker-Content-Digest: sha256:a19bb7ce8d3631fd8dc32540117046946d5357b9ad06d8cd1a991c9a3b062a6b

r8bind イメージ(のマニフェスト?)を削除します。

[root@registry docker]# curl -X DELETE -D - http://localhost:5000/v2/r8bind/manifests/sha256:a19bb7ce8d3631fd8dc32540117046946d5357b9ad06d8cd1a991c9a3b062a6b
HTTP/1.1 202 Accepted
Docker-Distribution-Api-Version: registry/2.0
X-Content-Type-Options: nosniff
Date: Fri, 01 Sep 2024 04:33:44 GMT
Content-Length: 0

r8bind イメージの実態を削除します。

[root@registry docker]# rm -rf /registry/docker/registry/v2/repositories/r8bind
[root@registry docker]#
参考:イメージの実態の削除(別の方法)

イメージの実態の削除は、registry コンテナにログインして行うこともできます。

[root@registry docker]# docker exec -it registry sh
/ # ls /var/lib/registry/docker/registry/v2/repositories
r8bind  r8stub
/ # rm -rf /var/lib/registry/docker/registry/v2/repositories/r8bind
/ #

registry コンテナを再起動します。

[root@registry docker]# docker restart registry
registry

registry コンテナが起動していることを確認します。

[root@registry docker]# docker ps -f name=registry
CONTAINER ID   IMAGE        COMMAND                   CREATED          STATUS          PORTS                                       NAMES
8c0459322715   registry:2   "/entrypoint.sh /etc…"   24 minutes ago   Up 20 seconds   0.0.0.0:5000->5000/tcp, :::5000->5000/tcp   registry

イメージ(r8bind)が削除されていることを確認します。

[root@registry docker]# curl -s http://localhost:5000/v2/_catalog | jq
{
  "repositories": [
    "r8stub"
  ]
}
補足:コンテナへの IP アドレスの追加

コンテナに IP アドレスを追加する例を示します。以下は r8bind コンテナに IPv4 と IPv6 を追加するコマンドです。

docker exec r8bind ip addr add 172.18.1.5/24 dev eth0
docker exec r8bind ip addr add fd00::5/64 dev eth0
タイトルとURLをコピーしました