DamienKarrus’s blog

プログラミングとクライミングの足跡

既存webシステムのコンテナ化(1) Docker実践-2

WSL2(debian latest)を使って既存のシステムのコンテナ化をしてみようと思う。 開発環境の構成は次の通り。

Windows10 professional
WSL2 (debian latest) 
Docker (20.10.17)

開発環境の構築手順はこちら damienkarrus.hatenablog.com

コンテナ化する対象のシステムは、CentOS7+Apache2+PHP7+PostgreSQL14で動作し、顧客用webページと、コンテンツ管理用の管理者ページがあり、それぞれURIを持っているが同一サーバで稼動している。DBは双方のwebページからアクセスされている。永続的に保存しなければいけないデータは、データベース、ユーザアップロードファイルである。 デバッグの効率性を考えて、PHPのソースはWindows上のフォルダに置き、それをdebianが勝手にマウントしてくれるので、そのdebianディレクトリをコンテナがbindして使う。デバッグ完了後は、bindせずに、コンテナ内にソースファイルを保持するようyamlに定義することにする。

Windowsフォルダのマウント状況は当環境では次のようになった。

Windows:
X:\oto\public_html ←管理者向けwebページ
X:/rega/public_html ←顧客向けwebページ
X:\oto\files ←アップロードされたファイル
 ↓
WSL(
WSL2(debian):
/mnt/x/oto/public_html
/mnt/x/rega/public_html
/mnt/x/oto/files

フォルダ構成

作業フォルダ(oto)を作成し、配下にDBとウェブアプリ(apache+php)のサブフォルダを作って、イメージはそれぞれの中でDockerfileで定義しておき、全体をdocker-composeでコントロールする。また、webサーバは一般公開用(web)とコンテンツ管理用(web2)があるので、2つのコンテナを用意し、それぞれがDBコンテナ、外部ボリュームコンテナを参照するように構築する。 oto下のファイル、ディレクトリ構成は以下の通り

docker-compose.yaml
postgres/
web/
web2/

postgres

postgresフォルダ内は

Dockerfile
docker-entrypoint-initdb.d/

Dockerfileは

FROM postgres:14-alpine
ENV LANG ja_JP.utf8
ENV TZ=Asia/Tokyo

docker-entrypoint-initdb.d には、データベースの初期データを data.out というファイル名でおいておくことにする(後ほどリストアして使用する)。
Postgresのデータはボリュームを作成しておきvolumeマウントして使う。

$ docker volume create --name oto-db

web , web2

webフォルダ / web2フォルダは

Dockerfile
php.ini
apache2.conf

phpの設定ファイルはbindして使用する(デバッグ・調整のため)。apacheはlatest、phpは7.4を指定した。 アップロードされたデータの保存先はボリュームを作成しておきvolumeマウントして使う。

$ docker volume create --name oto-files

Dockerfileは

FROM debian
ENV TZ=Asia/Tokyo
EXPOSE 80
RUN apt-get update
RUN apt-get install -y sudo
RUN apt-get install -y curl ca-certificates gnupg \
&& sudo apt-get install -y build-essential apt-transport-https \
&& sudo apt-get install -y php7.4 php7.4-intl php7.4-mbstring php7.4-pgsql php7.4-fpm php7.4-cli php7.4-zip \
&& sudo apt-get install -y apache2 libapache2-mod-php \
&& sudo apt-get install -y iputils-ping net-tools dnsutils \ ←疎通確認などに使用するツール
&& sudo apt-get clean \
&& rm -rf /var/lib/apt/lists/* \
&& rm /var/www/html/index.html
COPY apache2.conf /etc/apache2/
CMD /usr/sbin/apachectl -DFOREGROUND
STOPSIGNAL SIGWINCH

php.iniは

[PHP]
post_max_size = 1024M
upload_max_filesize = 1024M
max_file_uploads = 20
[Date]
date.timezone = "Asia/Tokyo"
[mbstring]
mbstring.internal_encoding = "UTF-8"
mbstring.language = "Japanese"

↑色々足りていないが、動作確認にはこれでOK

docker-compose

docker-compose.yaml

version: '3'
services:
  web:
    build: ./web
    ports:
      - 8080:80
    volumes:
      - ./web/php.ini:/usr/local/etc/php/php.ini
      - /mnt/x/oto/public_html:/var/www/html
      - oto-files:/var/www/html/files
  web2:
    build: ./web2
    ports:
      - 8081:80
    volumes:
      - ./web2/php.ini:/usr/local/etc/php/php.ini
      - /mnt/x/rega/public_html:/var/www/html
      - oto-files:/var/www/html/files
  db:
    build: ./postgres
    ports:
      - 5432:5432
    environment:
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: admin
    volumes:
      - ./postgres/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
      - oto-db:/var/lib/postgresql/data
volumes:
  oto-db:
    external: true
  oto-files:
    external: true

build前に既存システムのdbのバックアップを取り、postgres/docker-entrypoint-initdb.dに保存しておく

(既存システムで)
pg_dump cpan69 > data.out 

このファイルをpostgres/docker-entrypoint-initdb.d内にコピーしておく。
buildしてみる

$ docker-compose up --build -d
Building web
[+] Building 7.2s (11/11) FINISHED
...(snip)...
Creating oto_db_1   ... done
Creating oto_web2_1 ... done
Creating oto_web_1  ... done

稼働状況を確認する

$ docker-compose ps
   Name                  Command               State            Ports
------------------------------------------------------------------------------
oto_db_1     docker-entrypoint.sh postgres    Up      0.0.0.0:5432->5432/tcp
oto_web2_1   /bin/sh -c /usr/sbin/apach ...   Up      0.0.0.0:8081->80/tcp
oto_web_1    /bin/sh -c /usr/sbin/apach ...   Up      0.0.0.0:8080->80/tcp

コンテナ構築後の諸作業

疎通確認をする。まずはwebサーバにログインする。

$ docker container exec -it oto_web_1 /bin/bash

dbサーバにpingしてみる

# ping db
PING db (192.168.160.2) 56(84) bytes of data.
64 bytes from oto_db_1.oto_default (172.18.0.2): icmp_seq=1 ttl=64 time=0.081 ms
...(snip)...

DBのリストア

バックアップファイルをリストアする。dbサーバにログインする。

$ docker container exec -it oto_db_1 /bin/bash

DBに移植元のユーザとapache2のユーザを登録して、リストアし、apache2に対してgrant allをかける

# cd /docker-entrypoint-initdb.d
# createuser cpan69 ※現行システムがユーザcpan69で運用されているため、リストア時のエラー回避の為作成
# createuser www-data ※apache2のデフォルトユーザ名
# createdb cpan69
# psql -U admin cpan69 < data.out
# psql -U admin cpan69 < grantall.sql ※grant all on テーブル名 to www-data を記述したファイル

ソースファイルの修正

PostgreSQLのopenパラメータの調整 コンテナ化前はlocalhostを参照していたためhost指定を追加し、アクセスユーザも指定する。

$handler=pg_pconnect("dbname=$db_name");//コンテナ化前の記述
↓
$handler=pg_pconnect("host=db dbname=$db_name user=admin password=admin");

アップロード済みファイルを外部ボリュームへ展開する
元データのtarボールをソースファイルと同じところにおいておき、外部コンテナがマウントされている場所にて展開する まずはwebサーバにログインする。

$ docker container exec -it oto_web_1 /bin/bash

tarボールを展開する

# cd /var/www/html/files
# tar xf /var/www/html/msheet.tar .
# cd msheet
# cdmod 757 . ※apacheから書き込みが出来るよう許可
# chown www-data:www-data *.pdf ※apacheが書き込んだデータなのでオーナーをwww-dataに変更

ブラウザでlocalhostの8080と8081にアクセスし動作を確認する。

cronの設定

次にcrontabにスケジュールを登録する。実はここではまった。いつもはredhat系でcrontabにスケジュールを登録していたのだが、これでは時刻になっても発火しない。debian系だから?コンテナだから?ネットで検索するとbusyboxのcrondが良いとある。動作しない原因が不明なのは気持ち悪いが原因究明は別の機会にするとして、ここでは動作するものをインストールして使用することにする。 まずはモジュールをインストールするため、Dockerfileの記述を書き足す。

FROM debian
ENV TZ=Asia/Tokyo
EXPOSE 80
RUN apt-get update
RUN apt-get install -y sudo
RUN apt-get install -y curl ca-certificates gnupg \
&& sudo apt-get install -y build-essential apt-transport-https \
&& sudo apt-get install -y php7.4 php7.4-intl php7.4-mbstring php7.4-pgsql php7.4-fpm php7.4-cli php7.4-zip \
&& sudo apt-get install -y apache2 libapache2-mod-php \
&& sudo apt-get install -y iputils-ping net-tools dnsutils \
&& sudo apt-get install -y busybox-static \ ←これでcrondがインストールされる
&& sudo apt-get install -y vim \ ←viもインストールしておく
&& sudo apt-get clean \
&& rm -rf /var/lib/apt/lists/* \
&& rm -rf /var/www/html/* \
&& rm -rf /var/www/html/files
COPY apache2.conf /etc/apache2/
COPY crontab /var/spool/cron/crontabs/www-data ←crontabのコピー
CMD busybox crond -l 2 -L /dev/stderr -f & ←crondの起動 ※起動しない
CMD /usr/sbin/apachectl -DFOREGROUND
STOPSIGNAL SIGWINCH

crontabの内容は次の通り

00 11 * * * /bin/bash /var/www/html/cron.sh
00 07 * * 1 php /var/www/html/cli_shift_request_clear.php

※crondが起動しない。&を付けてもつけなくても起動しない。仕方ないので手動で起動した。

$ docker container exec -it otona_web_1 /bin/bash
root@d984e2b3e681:/# busybox crond -l 2 -L /dev/stderr -f &

※なお、EWSのEC2でdocker-composeすると、Dockerfile内にEXPOSE 80の記述があると、pullするときに404エラーになり落ちる

ここまでで、辛うじてコンテンツ自体はコンテナ化ができた。 次に定期的なバックアップをやってみる。 「既存webシステムのコンテナ化(2)」(現在作成中)に続く。

Windows10 Pro+WSL2+DebianでDockerを動かす

現行システムのコンテナ化を進めるにあたりまずは開発環境を構築する。作業PCはWindows10 Proである。

WSLのインストール

まずはWSLのインストールから(ホストOSはwindows10 Pro 21H1)
コマンドプロンプトを管理者権限で実行

> wsl --install
> dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
> dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all

Linuxカーネル更新プログラム パッケージをダウンロード
https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi

既定のバージョンとして WSL 2 を設定

> wsl --set-default-version 2

Linux ディストリビューションをインストール
https://aka.ms/wslstore Microsoft Apps Linuxの起動を簡単に行うために、Windows Terminalをインストールする

https://www.microsoft.com/ja-jp/p/windows-terminal/9n0dx20hk701?activetab=pivot:overviewtab

LinuxからWindows上のファイルにアクセスするには
/mnt/c
WindowsからLinuxUbuntu)上のファイルにアクセスするには
\wsl$\Ubuntu

Dockerのインストール

Debianでdockerをセットアップする。少し癖がある。

$ sudo apt-get update
$ sudo apt-get install ca-certificates curl gnupg lsb-release \
https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
$ echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable" | $ $ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin
$ docker -v
$ docker image
docker: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?.

なんとサービスが動いてない。サービスをスタートしてみる。

$ sudo service docker start
grep: /etc/fstab: No such file or directory
[ ok ] Starting Docker: docker.

今度はfstabがないといわれる。確かにない。fstabをつくる。

$ sudo touch /etc/fstab
$ sudo update-alternatives --set iptables /usr/sbin/iptables-legacy
$ sudo update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy
$ sudo service docker start
[ ok ] Starting Docker: docker.
$ sudo service docker status
[ ok ] Docker is running.

以上でdockerが動作する

Windows 11 Homeの場合の構築方法

damienkarrus.hatenablog.com

crontabへのスケジュール登録

crontabにファイルを使ってスケジュールを一括登録する。
この方式は既存のスケジュールを消去して新たに新規登録するため、まずは現在のスケジュールをバックアップしておき、そのバックアップデータを修正して新たなスケールを作成し一括登録する手順で行うこととする。まずは現在のスケジュールをバックアップする。

$ crontab -l > aaa
$ cp -p aaa crontab-data_`date "+%Y%m%d"`
$ ll
-rw-rw-r--  1 cpan69 cpan69      621 Aug 28 09:35 aaa
-rw-rw-r--  1 cpan69 cpan69      621 Aug 28 09:35 crontab-data_20220828

バックアップした現在のcrontabデータを修正する。

$ vi aaa

編集後、crontabへ登録する。

$ crontab aaa

登録内容の確認

$ crontab -l

LAPP on コンテナ on WSL2

WSLを使って開発環境(LAPP)をコンテナで作ってみようと思う。 ホスト側環境は以下の通り

Windows11
WSL2 (Ubuntu-20.04)
Docker (20.10.14)

デバッグの効率性を考えて、PHPのソースはWindows上のフォルダに置き、それをUbuntuが勝手にマウントしてくれるので、そのUbuntuディレクトリをコンテナがbindして使う。

Windows:C:\Users\kakimoto\mpses
 ↓
Ubuntu:/mnt/c/Users/kakimoto/mpses

フォルダ構成

作業フォルダ(mpses)下にDBとウェブアプリ(apache+php)のサブフォルダを作って、イメージはそれぞれの中で作成定義しておき、全体をdocker-composeでコントロールする。

docker-compose.yaml
postgres/
web/

postgres

postgresフォルダ内は

Dockerfile
docker-entrypoint-initdb.d/

Dockerfileは

FROM postgres:14-alpine
ENV LANG ja_JP.utf8

docker-entrypoint-initdb.d には、データベースの初期データを data.out というファイル名でおいておくことにする(後ほどリストアして使用する)。
Postgresのデータはボリュームを作成しておきvolumeマウントして使う。

$ docker volume create --name mps-db-data

web

webフォルダは

Dockerfile
php.ini
apache2.conf
src/

apachephpの設定ファイルはbindして使用する。apacheはlatest、phpは7.4を指定した。srcはwindows上のソースファイルがあるフォルダ。
Dockerfileは

FROM debian
EXPOSE 80
RUN apt-get update
RUN apt-get install -y sudo
RUN apt-get install -y curl ca-certificates gnupg \
&& sudo apt-get install -y build-essential apt-transport-https \
&& sudo apt-get install -y php7.4 php7.4-intl php7.4-mbstring php7.4-pgsql php7.4-fpm php7.4-cli php7.4-zip \
&& sudo apt-get install -y apache2 libapache2-mod-php \
&& sudo apt-get install -y iputils-ping net-tools dnsutils \ ←疎通確認などに使用するツール
&& sudo apt-get clean \
&& rm -rf /var/lib/apt/lists/* \
&& rm /var/www/html/index.html
COPY php.ini /usr/local/etc/php/
COPY apache2.conf /etc/apache2/
CMD /usr/sbin/apachectl -DFOREGROUND
STOPSIGNAL SIGWINCH

php.iniは

[Date]
date.timezone = "Asia/Tokyo"
[mbstring]
mbstring.internal_encoding = "UTF-8"
mbstring.language = "Japanese"

docker-compose

doker-compose.yaml

version: '3'
services:
  web:
    build: ./web
    volumes:
      - ./web/php.ini:/usr/local/etc/php/php.ini
      - ./web/src:/var/www/html
    ports:
      - 8080:80
  db:
    build: ./postgres
    ports:
      - 5432:5432
    environment:
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: admin
    volumes:
      - ./postgres/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
      - mps-db-data:/var/lib/postgresql/data
volumes:
  mps-db-data:
    external: true

まずは疎通確認

# ping db
PING db (192.168.160.2) 56(84) bytes of data.
64 bytes from mpses_db_1.mpses_default (192.168.160.2): icmp_seq=1 ttl=64 time=0.081 ms
...(snip)...

では、webコンテナからdbコンテナに対してSQLを発行してみる。次のphpを作ってブラウザでアクセスしてみる。内容はテーブル一覧を表示するというもの。
mpses/web/src/test.php

<?php
        ini_set( 'display_errors' , 'On' );
        $str = "host=db port=5432 dbname=admin user=admin password=admin";
        $db = pg_connect( $str );
        if($db == FALSE):
                echo "DB connection failed DAME";
                exit;
        endif;
        $q = "select schemaname, tablename, tableowner from pg_tables where schemaname not like 'pg_%' and schemaname != 'information_schema'";
        $res = pg_query( $db , $q );
        $rows = pg_num_rows( $res );
        for( $i=0 ; $i<$rows ; $i++ ):
                $e = pg_fetch_array( $res , $i , PGSQL_ASSOC );
                print( "$i: {$e['schemaname']} , {$e['tablename']} , {$e['tableowner']} <br />" );
        endfor;
?>

1行目はエラーが出た場合にメッセージを画面に表示すための指定。 2行目がpg_connect()に渡すパラメータ。今回の接続内容は、

キー パラメータ 説明
host db postgresコンテナのホスト名=docker-compose.yaml内のdbコンテナのサービス名
port 5432 docker-compose.yaml内で指定した外向けport番号
dbname admin db名称:今回は明示的に指定しなかったので、USER名と同じ名称となっている
user admin docker-compose.yaml内で指定したユーザ名
password admin docker-compose.yaml内で指定したパスワード

ここまでで一応、apacheが動き、phpが動き、それぞれの設定ファイルを自由に設定でき、postgresのコンテナを分離でき、データベースクラスタ(物理的記憶領域)を外部のボリュームに逃がしてみることができた。基本的な開発環境としては最低限なところは構築できたと思う。

Windows10 Professionalの場合の構築方法

damienkarrus.hatenablog.com

PostgreSQLのコンテナを作る Docker実践-1 

DBのコンテナを作ってみる。 PostgreSQLの14.xで作成することにする。カレントディレクトリを mpses とする。 Dockerfileはpostgresフォルダを作りその中に入れる

mpses/postgres/

Dockerfileを作る

FROM postgres:14-alpine
ENV LANG ja_JP.utf8

debian版とalpine版があるが、alpineのほうががサイズが小さい
次に docker-compose.yaml で起動時の初期設定を書く。Dockerfile 内で docker run しないのは、起動時の設定を覚えるのが大変だから。 docker-compose.yaml にその設定を書いてしまえばよい。

version: '3'
services:
  db:
    build: ./postgres
    ports:
      - 5432:5432
    environment:
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: admin

dbという名称は任意に付けたもの。ユーザ名を指定しないとデフォルトのpostgresになる。
コンテナを起動する

$ docker-compose up -d ←デタッチモード

面倒なパラメータはdocker-composeに入っているので何も指定しなくてよい。起動されているか確認してみる。

$ docker container exec -it mpses_postgres_1 /bin/bash
bash-5.1# psql -U admin
psql (14.2)
Type "help" for help.

admin=# select version();
                                                   version
--------------------------------------------------------------------------------------------------------------
 PostgreSQL 14.2 on x86_64-pc-linux-musl, compiled by gcc (Alpine 10.3.1_git20211027) 10.3.1 20211027, 64-bit
(1 row)

admin=# \q
bash-5.1# exit
$ docker-compose down

version14.2が稼働していることが確認できた。
次はコンテナ起動時にDBにデータを入れてみる。なお、adminというユーザを登録した場合はadminというデータベースも作られているので、データベースをcreateする必要はない。
postgres の docker image は、docker-entrypoint-initdb.d 内に.sh を置いておくと起動時にその内容を実行してくれる。 postgresフォルダ内に docker-entrypoint-initdb.d フォルダを作り、以下のinit.shファイルを置いてみる。
init.sh

set -e
psql -U admin admin <<EOF
CREATE TABLE m_user(
id TEXT PRIMARY KEY,
name TEXT,
password TEXT
);
EOF

docker-composeファイルに、volume設定を定義してこのファイルを参照させる。

version: '3'
services:
  db:
    build: ./postgres
    ports:
      - 5432:5432
    environment:
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: admin
    volumes:
      - ./postgres/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d

コンテナを立ち上げて、DBを確認してみる。

$ docker-compose up -d
$ docker container exec -it mpses_postgres_1 /bin/bash
bash-5.1# psql -U admin
psql (14.2)
Type "help" for help.

admin=# \d
        List of relations
 Schema |  Name  | Type  | Owner
--------+--------+-------+-------
 public | m_user | table | admin
(1 row)

admin=# \d m_user
              Table "public.m_user"
  Column  | Type | Collation | Nullable | Default
----------+------+-----------+----------+---------
 id       | text |           | not null |
 name     | text |           |          |
 password | text |           |          |
Indexes:
    "m_user_pkey" PRIMARY KEY, btree (id)

admin=#

指定した通りに生成できているようだ。 ここで一旦コンテナを削除する。

$ docker-compose down

次に、既存のDBをリストアしてみる。
バックアップファイルを docker-entrypoint-initdb.d フォルダに data.out というファイル名で用意する。init.shは不要なので削除しておく。
また、データを永続的に保存するため、ホスト側のディレクトリをマウントしたい。ところが、ホスト側(Windows)をマウントしても、書き込み権限エラーやSYNCエラーが多発する。おそらくLinuxが仮想ファイルシステムWindows上で動かしているとおもわれるがこれが良くないみたいだ。そこでdockerでvolumeを作り、それを利用することにする。

$ docker volume create mps-db-data

docker-compose.yamlは以下の通り

version: '3'
services:
    db:
        build: ./postgres
            ports:
                - 5432:5432
            environment:
                POSTGRES_USER: admin
                POSTGRES_PASSWORD: admin
            volumes:
                - mps-db-data:/var/lib/postgresql
                - ./postgres/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
volumes:
  mps-db-data:
    external:true

コンテナに入り、バックアップデータをリストアする。

$ docker-compose up -d
$ docker-compose exec db bash
# cd /docker-entrypoint-initdb.d
# psql -U admin < data.out
...(snip)...
# psql -U admin
admin=# \d
テーブルやレコードの存在することを確認する
admin=# \q
# exit

これでデータベースの内容はvolume内に保存されたはずである。確認のため、コンテナを削除してから再構築し、データが保存されていることを確認してみる。

$ docker-compose down
$ docker container ls ←消えている
$ docker network ls ←消えている
$ docker volume ls ←volumeは残っている
DRIVER    VOLUME NAME
local     mps-db-data
$ docker-compose up -d
$ docker-compose exec db bash
# psql -U admin
admin=# \d
テーブルやレコードの存在することを確認する
admin=# \q
# exit
$ docker-compose down

DBデータの永続化ができた。くれぐれもdocker volume prune で消しませんように......

次の記事 damienkarrus.hatenablog.com

PHP8.1+PostgreSQL14.2の最新LAPP環境構築

本日時点での最新PHPと最新PostgresでLAPP環境を構築するにはこうします

sudo apt-get update 
sudo apt-get install -y curl ca-certificates gnupg 
curl https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
sudo apt-get install -y postgresql 
sudo apt-get install -y build-essential apt-transport-https 
sudo add-apt-repository -y ppa:ondrej/php 
sudo apt-get install -y php8.1 php8.1-intl php8.1-mbstring php8.1-pgsql php8.1-fpm php8.1-cli php8.1-zip
sudo apt-get install -y apache2 libapache2-mod-php 
sudo apt-get clean 
rm -rf /var/lib/apt/lists/* 

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

$ php -v
PHP 8.1.3 (cli) (built: Feb 21 2022 14:48:42) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.1.3, Copyright (c) Zend Technologies
    with Zend OPcache v8.1.3, Copyright (c), by Zend Technologies

無事8.1が入っています。 Posgreのバージョンを確認します。

$ sudo -u postgres -i
$ psql
psql (14.2 (Ubuntu 14.2-1.pgdg20.04+1)) ←psqlのバージョンです。本体のバージョンではない。
Type "help" for help.
postgres=# select version();
                                                             version                                                            
----------------------------------------------------------------------------------------------------------------------------------
 PostgreSQL 14.2 (Ubuntu 14.2-1.pgdg20.04+1) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0, 64-bit
(1 row)

SELECT version(); として表示されるのが本体のバージョンで、14.2がインストールされました。

WSL2のインストール(windows11)

WSL2(Windows Subsystem for Linux2)はWindowsOS上で仮想マシンとしてLinuxカーネルを動作させるサブシステムである。
インストールするWindowsエディションやバージョンによってインストール工程は異なる。今回インストールの対象としたのは、以下のマシンである。

エディション:Windows 11 Home
バージョン:21H2 (OSビルド 22000.556)

Windows11 (21H2)へのWSL2インストールは容易である。 Windows PowerShellを管理者権限で立ち上げる。 wslのインストール指示をする。

> wsl --install

以下のようにメッセージが出てインストールが終了するので、再起動する。

インストール中: 仮想マシン プラットフォーム
仮想マシン プラットフォーム はインストールされました。
インストール中: Linux 用 Windows サブシステム
Linux 用 Windows サブシステム はインストールされました。
ダウンロード中: WSL カーネル
インストール中: WSL カーネル
WSL カーネル はインストールされました。
ダウンロード中: GUI アプリ サポート
インストール中: GUI アプリ サポート
GUI アプリ サポート はインストールされました。
ダウンロード中: Ubuntu
要求された操作は正常に終了しました。変更を有効にするには、システムを再起動する必要があります。

再起動すると、Ubuntuのインストールが始まり、使用するユーザ名とパスワードの入力が求められる。

Installing, this may take a few minutes...
Please create a default UNIX user account. The username does not need to match your Windows username.
For more information visit: https://aka.ms/wslusers
Enter new UNIX username: ubuntu
New password:
Retype new password:
passwd: password updated successfully
Installation successful!

これで完了である。ただ、su はできない。sudo を使えと言っている。

To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

以上のやりかたでUbuntuの最新バージョンがインストールされるが、Ubuntuの最新以外をインストールしたい場合は、インストール時にディストリビューションを指定すればよい。 ディストリビューションの一覧は次のように確認できる。

> wsl -l -o
インストールできる有効なディストリビューションの一覧を次に示します。
'wsl --install -d <Distro>' を使用してインストールします。

NAME            FRIENDLY NAME
Ubuntu          Ubuntu
Debian          Debian GNU/Linux
kali-linux      Kali Linux Rolling
openSUSE-42     openSUSE Leap 42
SLES-12         SUSE Linux Enterprise Server v12
Ubuntu-16.04    Ubuntu 16.04 LTS
Ubuntu-18.04    Ubuntu 18.04 LTS
Ubuntu-20.04    Ubuntu 20.04 LTS

メッセージにあるように、仮にDebianをインストールする場合は

> wsl --install -d Debian 

とすればよい。
ディストリビューションのアンインストールは unregisterを使用する。

> wsl --unregister ディストリビューション名

PowerShellからUbuntuのシェルを起動するにはwslコマンドを実行する

> wsl

ただwslとした場合はデフォルトのディストリビューションのシェルが起動する。ディストリビューション名を指定することによって切り替えることができる。

これだけではWSLとして動作しているのか、それともWSL2として動作しているaかよくわからない。確認してみる。

> wsl -l -v
  NAME      STATE           VERSION
* Ubuntu    Running         2

VERSION欄に2と表示されているので、どうやら大丈夫そうである。 では、まっさらなUbuntuを調整していく。まずはバージョンの確認。

$ lsb_release -a

aptのリポジトリを最新に更新

$ sudo apt update 
$ sudo apt upgrade -y

新しいユーザを登録する

$ sudo adduser mpses
$ sudo passwd mpses

wslで起動時に特定ユーザでログインしたい場合は-uを使用する

> wsl -u mpses

デフォルトユーザを変更したい場合はubuntu2004コマンド(ubuntu-20.04のexe)で行う

> ubuntu2004 config --default-user mpses

また、rootでログインするには

> wsl  -u root

ネットワークについて
ホスト(Windows)側
IPアドレスは固定ではない

> ipconig
...(snip)...
イーサネット アダプター vEthernet (WSL):

   接続固有の DNS サフィックス . . . . .:
   リンクローカル IPv6 アドレス. . . . .: fe80::59b4:3821:1389:e888%31
   IPv4 アドレス . . . . . . . . . . . .: 172.17.224.1
   サブネット マスク . . . . . . . . . .: 255.255.240.0
   デフォルト ゲートウェイ . . . . . . .:

ゲスト(WSL2)側
IPアドレスは固定ではない

$ ip addr | grep eth0
6: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    inet 172.17.226.110/20 brd 172.17.239.255 scope global eth0

Ubuntu内で立ち上げたhttpdwindows側からアクセスしてみる

$ sudo apt-get install -y apache2
$ apache2 -v
$ sudo service apache2 restart
$ sudo service apache2 status
$ curl http://localhost/

これでhtmlがバラバラ表示されればokだ Windows側からアクセスしてみる。ブラウザでhttp://localhost/で表示される。
あれ? ホスト側IPアドレスじゃなくてlocalhost? ちょっと不思議ですね。
Ubuntuの日本語化
使用できるロケールを確認

$ locale -a
C
C.UTF-8
POSIX
en_US.utf8

日本語がないので、日本語言語パックをインストールする

$ sudo apt install -y language-pack-ja
...(snip)...
$ locale -a
C
C.UTF-8
POSIX
en_US.utf8
ja_JP.utf8

日本語が入った。ロケールをja_JP.UTF-8に設定する。

$ sudo update-locale LANG=ja_JP.UTF-8

ここで一旦ログアウトする。 タイムゾーンJSTに設定する。

$ sudo dpkg-reconfigure tzdata

アジア→東京 TABで<了解>を選ぶ。
日本語manページのインストールをしておく。

$ sudo apt -y  install manpages-ja manpages-ja-dev