既存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からLinux(Ubuntu)上のファイルにアクセスするには
\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の場合の構築方法
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/
apacheやphpの設定ファイルは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の場合の構築方法
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 で消しませんように......
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内で立ち上げたhttpdにwindows側からアクセスしてみる
$ 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