[Docker] イメージの保存と読み込み

– 作成したイメージをファイル化すると、別のコンピュータに持っていくことができる。
– ファイル化にはdocker saveを使う。
– ファイルから取り出すには docker loadを使う。

### docker saveでイメージからファイル化
$ sudo docker save -o saved.tar myphpimage
$ ls -al saved.tar
-rw——- 1 root root 262609920 Mar 24 07:19 saved.tar

内容確認
$ sudo tar tvf saved.tar

### docker loadする
$ sudo docker image rm myphpimage
$ sudo docker load -i saved.tar
$ sudo docker image ls
$ sudo docker stop myphp02
$ sudo docker rm myphp02


export/importによるファイル化
L コンテナ情報が失われるためあまり使用しない

なるほど、Docker hubなどを使わなくても、tarファイルに出来るんだね
中々勉強になるわ…

[Docker] コマンドの実行

コマンドの実行系統の命令は「RUN」「CMDとENTRYPOINT」の2種類ある
前者はイメージ作成時、後者はコマンドの実行時

### RUN
RUNコマンドはdocker buildするタイミング
(1)シェル形式
/bin/sh -cを経由してコマンドが実行
RUN ${コマンド} ${引数} …

(2)exec形式
実行したいコマンドや引数を[]を囲んで記述
RUN [“コマンド”, “引数”, …]

RUNコマンドごとにレイヤーが増えるので、一つのコマンドで実現できる様にする
RUN コマンド1 && コマンド2 && コマンド3

ONBUILD COPY コピー元 コピー先

### CMDとENTRY POINT
コンテナを起動したときのタイミングでコンテナの中で実行するコマンドを指定する
(1)ENTRY POINT: コマンドの指定を強要する。イメージの利用者はこの設定を変更することはできない。
docker runの最後に指定するコマンドは、ENTRYPOINTで指定したコマンドへの引数となる

(2)CMD
docker runの際に指定する最後のコマンドのデフォルト値を変更

殆どの場合、CMDが使われる
イメージが通信しようとするポート番号はEXPOSEで指定する

### HTTPDのDockerfile
https://github.com/docker-library/httpd/blob/master/2.4/Dockerfile

phpimage/index.php

<body>
	Your IP <?php echo $_SERVER['REMOTE_ADDR']; ?>。
</body>

Dockerfile

FROM debian
EXPOSE 80
RUN apt update \
&& apt install -y apache2 php libapache2-mod-php \
&& apt clean \
&& rm -rf /var/lib/apt/lists/* \
&& rm /var/www/html/index.html
COPY index.php /var/www/html
CMD /usr/sbin/apachectl -DFOREGROUND

apt clean, rm -rf /var/lib/apt/lists/* でパッケージを削除する。常套句。
中間ファイルを削除することで、Dockerイメージのサイズを小さくできる
CMD /usr/sbin/apachectl -DFOREGROUND でapacheをフォアグラウンドで実行する

$ sudo docker build . -t myphpimage
$ sudo docker images;
REPOSITORY TAG IMAGE ID CREATED SIZE
myphpimage latest 5c4aa75b77ce 4 minutes ago 254MB

– コンテナを動かす
$ sudo docker run -dit –name myphp -p 8080:80 myphpimage

キャッシュを活用するとビルドを高速化できる
キャッシュを使わない場合は、docker build . -t myphpimage –no-cache とする

なるほど、Dockerfileの作成は練習が必要だな…

[Docker] fileのbuild

Dockerfile

FROM httpd
COPY index.html /usr/local/apache2/htdocs/

1行目はFROM命令
「#」はコメント
行を跨ぐときは末尾に「¥」を記述
「${環境変数}」は環境変数

index.html

<body>
	<h1>Docker Test</h1>
</body>

### イメージをビルド
$ sudo docker build -t myimage01 .
$ sudo docker images;
REPOSITORY TAG IMAGE ID CREATED SIZE
myimage01 latest b2397acb1a5a 43 seconds ago 144MB
$ sudo docker history myimage01;
IMAGE CREATED CREATED BY SIZE COMMENT
b2397acb1a5a About a minute ago /bin/sh -c #(nop) COPY file:752610804eacad0e… 213B

$ sudo docker run -dit –name webcontent_docker -p 8080:80 myimage01
7528440013bfa467f5e06d4f4a0b3eec0182ae5bb433d6045ee52611119f2b7c

http://192.168.56.10:8080/

なるほどー

### Dockerfileのコマンド
FROM
ベースイメージを指定する
ADD
イメージにファイルやフォルダを追加する。Dockerfileを置いたディレクトリ外のリモートファイルも指定できる。圧縮ファイルを指定したときは自動的に展開される。
COPY
イメージにファイルやフォルダを追加する。Dockerfileを置いたディレクトリ内のファイルしか指定できない。圧縮ファイルを指定したときは、圧縮ファイルのままコピーされる。
RUN
イメージをビルドするときにコマンドを実行する。
CMD
コンテナを起動するときに実行する既定のコマンド(docker createやdocker runで実行するコマンドを省略したとき)を指定する
ENTRYPOINT
イメージを実行するとき(docker createやdocker runするとき)のコマンドを強要する
ONBUILD
ビルド完了したときに任意の命令を実行する
EXPOSE
通信を想定するポートをイメージの利用者に伝える
ONBUILD
ビルドが完了したときに任意の命令を実行する
EXPOSE
通信を想定するポートをイメージの利用者に伝える
VOLUME
永続データが保存される場所をイメージの利用者に伝える
ENV
環境変数を定義する
WORKDIR
RUN, CMD, ENTRYPOINT, ADD, COPYの際の作業ディレクトリを指定する
SHELL
ビルド時のシェルを指定する
LABEL
名前やバージョン番号、制作者情報などを設定する
USER
RUN、CMD、ENTRYPOINTで指定するコマンドを実行するユーザやグループを設定する(USERを指定しない場合はroot)
ARG
docker buildする際に指定できる引数を宣言する
STOPSIGNAL
docker stopする際に、コンテナで実行しているプログラムに対して送信するシグナルを変更する(規定は)
HEALTHCHECK
コンテナの死活確認をするヘルスチェックの方法をカスタマイズする

[Docker] コンテンツ入りのhttpdコンテナを作る

1. httpdコンテナを起動する
$ sudo docker run -dit –name webcontent -p 8080:80 httpd:2.4
$ sudo docker cp tmp/index.html webcontent:/usr/local/apache2/htdocs

2. コンテナをイメージ化する
docker commitコマンドを使う
$ sudo docker commit webcontent mycustomed_httpd
$ sudo docker images;
REPOSITORY TAG IMAGE ID CREATED SIZE
mycustomed_httpd latest 3239a258d78d 10 seconds ago 144MB
$ sudo docker image history mycustomed_httpd
IMAGE CREATED CREATED BY SIZE COMMENT
3239a258d78d About a minute ago httpd-foreground 219B
b9bd7e513e0f 3 days ago /bin/sh -c #(nop) CMD [“httpd-foreground”] 0B
3 days ago /bin/sh -c #(nop) EXPOSE 80 0B

3. カスタムなイメージを使う
$ sudo docker run -dit –name webcontent_new -p 8081:80 mycustomed_httpd
$ sudo docker ps
$ sudo docker exec -it webcontent_new /bin/bash
root@6bbe9d0c262d:/usr/local/apache2# cat /usr/local/apache2/htdocs/index.html

4. 後始末
$ sudo docker stop webcontent webcontent_new
$ sudo docker rm webcontent webcontent_new
$ sudo docker rmi mycustomed_httpd

ニャルほどー
3連休、こればっかりやってるけど、進んでる感じがしないなー
まあ、理解はかなり進んだが…

[Docker] イメージの自作

httpdイメージには、PHPをインストールするためのパッケージやビルドするための環境などが含まれていない

### よく使われるベースイメージ
debian: なんでもしたいときはdebianが多い
ubuntu: ubuntuフルセット
alpine: muslとBusyBoxをベース パッケージマネージャが付属しているため、busyboxよりこちらの方が使い勝手が良い
busybox: 組み込み目的で作られた小さいLinux

※2.4-alpineなどはalpineをベースに作られたもの
Linuxカーネルは、その下で動いているUbuntuのものなどが使われる。コンテナの中にカーネルはない

– レイヤーの確認(mysqlのレイヤーを確認する)
$ sudo docker image rm mysql:5.7
$ sudo docker pull mysql:5.7
5.7: Pulling from library/mysql
a4b007099961: Pull complete
e2b610d88fd9: Pull complete
38567843b438: Pull complete
5fc423bf9558: Pull complete
aa8241dfe828: Pull complete
cc662311610e: Pull complete

「a4b007…」「e2b610…」「38567…」がレイヤーに相当するイメージ

– Dockerの流儀に従って作る
Dockerfileのベストプラクティス
https://docs.docker.jp/engine/articles/dockerfile_best-practice.html
– 1つのコンテナは1つの処理しかしない
– 利用するポートを明確にする
– 永続化すべき場所を明確にする
– 設定は環境変数で渡す
– ログは標準出力に書き出す
– メインプログラムが終了するとコンテナが終了

ベースイメージに何を使うべきなのかずっと疑問だったが、ある程度理解できた。
バッチのところがやや課題か…

[Docker] Docker Composeの仕組み

Docker Composeは、あらかじめコンテナの起動方法やボリューム、ネットワーク構成などを書いた定義ファイルを用意しておき、その定義ファイルっを読み込ませることでまとめて実行する方法
Docker ComposeはPython製のツール

$ sudo docker-compose –version

docker-compose.yml

version: '3'

services:
  wordpress-db:
    image: mysql:5.7
    networks:
      - wordpressnet
    volumes:
      - wordpress_db_volume:/var/lib/mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: myrootpassword
      MYSQL_DATABASE: wordpressdb
      MYSQL_USER: wordpressuser
      MYSQL_PASSWORD: wordpresspass

  wordpress-app:
    depends_on:
      - wordpress-db
    image: wordpress
    networks:
      - wordpressnet
    ports:
      - 8080:80
    restart: always
    environment:
      WORDPRESS_DB_HOST: wordpress-db
      WORDPRESS_DB_NAME: wordpressdb
      WORDPRESS_DB_USER: wordpressuser
      WORDPRESS_DB_PASSWORD: wordpresspass

networks:
  wordpressnet:

volumes:
  wordpress_db_volume:

### Docker Compose操作
$ sudo docker-compose up -d
$ sudo docker-compose ps
Name Command State Ports
———————————————————————————————————
wordpress_wordpress-app_1 docker-entrypoint.sh apach … Up 0.0.0.0:8080->80/tcp,:::8080->80/tcp
wordpress_wordpress-db_1 docker-entrypoint.sh mysqld Up 3306/tcp, 33060/tcp
$ sudo docker network ls
$ sudo docker volume ls

### コンテナを停止して破棄
$ sudo docker-compose down

### Docker-compose.ymlの書き方
1. サービス
2. ネットワーク
3. ボリューム

image:wordpress
image:
wordpress
depends_on: この定義によって、後に起動できる

– ネットワークの指定省略
明示的にネットワークを指定しなかったときは、記述しているサービスが繋がるDockerネットワークを自動的に作成し、全てのサービスをそのネットワークに接続するように構成する

– サービスを個別に操作
docker-compose logs
docker-compose rm
docker-compose run
docker-compose exec
docker-compose start
docker-compose stop

うむー進むのだけは早い

[Docker] WordPressを構築する

1. Dockerネットワークを作成
$ sudo docker network create wordpressnet
$ sudo docker network ls

2. ボリュームの作成
$ sudo docker volume create wordpress_db_volume
$ sudo docker volume ls

3. mysqlコンテナを起動
$ sudo docker run –name wordpress-db -dit -v wordpress_db_volume:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=myrootpassword -e MYSQL_DATABASE=wordpressdb -e MYSQL_USER=wordpressuser -e MYSQL_PASSWORD=wordpresspass –net wordpressnet mysql:5.7

4. WordPressコンテナを起動
$ sudo docker run –name wordpress-app -dit -p 8080:80 -e WORDPRESS_DB_HOST=wordpress-db -e WORDPRESS_DB_NAME=wordpressdb -e WORDPRESS_DB_USER=wordpressuser -e WORDPRESS_DB_PASSWORD=wordpresspass –net wordpressnet wordpress

$ sudo docker stop wordpress-db wordpress-app
$ sudo docker rm wordpress-db wordpress-app
$ sudo docker network rm wordpressnet
$ sudo docker volume rm wordpress_db_volume

うん、割と簡単

[Docker] Dockerネットワーク

Dockerネットワークを作ることで、コンテナ名で通信できるようになる

### Dockerネットワークの作成
$ sudo docker network create mydockernet
$ sudo docker network ls
$ sudo docker network inspect mydockernet

明示的にipアドレスの範囲を指定することもできる
$ sudo docker network create examplenet –subnet 10.0.0.0/16 –gateway 10.0.0.1

### Dockerネットワークにコンテンツを作る
$ sudo docker run -dit –name web01 -p 8080:80 –net mydockernet httpd:2.4
$ sudo docker run -dit –name web02 -p 8081:80 –net mydockernet httpd:2.4
$ sudo docker network inspect mydockernet
※connectやdisconnectを使って、コンテナを破棄せずに接続したり切断できる
$ sudo docker run –rm -it –net mydockernet ubuntu /bin/bash
# apt update
# apt -y upgrade
# apt install -y iproute2 iputils-ping curl
# ping -c 4 web01
# curl http://web01/

### Dockerネットワークの削除
$ sudo docker stop web01 web02
$ sudo docker rm web01 web02
$ sudo docker network rm mydockernet

ok, そこそこ進んでるような気がする…

[Docker] ネットワーク

– 三つのネットワーク: bridge, host, none
bridgeがよく使われる

$ sudo docker run -dit –name web01 -p 8080:80 httpd:2.4
$ sudo docker run -dit –name web02 -p 8081:80 httpd:2.4

$ sudo docker container inspect web01
– NetworkSettingsの部分にIPアドレスが記載される
“IPAddress”: “172.17.0.2”,

$ sudo docker container inspect –format=”{{.NetworkSettings.IPAddress}}” web01
172.17.0.2
$ sudo docker container inspect –format=”{{.NetworkSettings.IPAddress}}” web02
172.17.0.3

接続されているコンテナのIPアドレス一覧
$ sudo docker network inspect bridge
ホストのIP
# sudo apt install net-tools
$ ifconfig
$ sudo iptables –list -t nat -n

### Dockerホスト同士の通信
bridgeネットワークに接続されているため、コンテナ同士で通信ができる

$ sudo docker run –rm -it ubuntu /bin/bash
# apt update
# apt -y upgrade
# apt install -y iproute2 iputils-ping curl
# ip address
# ping -c 4 172.17.0.2
# ping -c 4 172.17.0.3
# curl http://172.17.0.2/
# curl http://172.17.0.3/

Dockerネットワークを作成、–linkオプションを指定で通信相手を特定できる
$ sudo docker run –rm -it –link web01:web01 –link web02:web02 ubuntu /bin/bash
※linkオプションを使うことでコンテナ名で通信ができるようになる

ニャルほどー
前進してるようなしてないような…

[Docker] データのバックアップ

別のディレクトリにコピーするか、tarコマンドでファイルをまとめて保存するかなどでバックアップできる。

### ボリュームの場所
$ sudo docker volume inspect mysqlvolume
[
{
“CreatedAt”: “2022-03-21T05:36:02Z”,
“Driver”: “local”,
“Labels”: {},
“Mountpoint”: “/var/lib/docker/volumes/mysqlvolume/_data”,
“Name”: “mysqlvolume”,
“Options”: {},
“Scope”: “local”
}
]

### ボリュームバックアップの考え方
適当なコンテナを割り当てて、そのコンテナを使ってバックアップを取る
/tmpなどのディレクトリにバック対象のコンテナをマウントし、tarでバックアップを作成
バックアップ中はコンテナを停止しておくのが望ましい

### ボリュームバックアップの慣例的なコマンド
$ sudo docker run –rm -v mysqlvolume:/src -v “$PWD”:dest busybox tar czvf /dest/backup.tar.gz -C /scr .
$ ls
backup.tar.gz
$ tar tzvf backup.tar.gz

### ボリュームをリストア
$ sudo docker volume rm mysqlvolume
$ sudo docker volume create mysqlvolume
$ $ sudo docker run –rm -v mysqlvolume:/dest -v “$PWD”:/src busybox tar xzf /src/backup.tar.gz -C /dest

なるほど、なかなか凄いな
全然終わる気配がないな