Docker・CI/CDのブートストラップ講座
2年ほど前に受講した大名エンジニアカレッジの発展コース講座のメモをScrapBoxに移した。走り書きのメモしかないが。。。 目的
なぜDcokerが優れているかわかる、メリットがわかる
Dcokerを採用した方がいいかどうか判断できる
Dcokerで自分のアプリケーションをコンテナ化できるようになる
docker-composeを学ぶ
単語の説明
コンテナ技術=カーネルを共有し、名前空間が分離されたプロセス
カーネル=ハードウェア資源をプロセスが使えるようにするためのソフトウェア
名前空間=プロセス番号やネットワーク資源(IP, ポート)を共有することはできない
Docker=コンテナ技術の一つがdockerである
イメージ
イメージ=コンテナが参照するファイル群をパッケージ化して保存したもの
イメージの実体はアプリケーションのファイル群のまとまり+実行環境で、このイメージさえあればアプリケーションがどんな環境でも動かせる状態が望ましい。
アプリケーションを含まないイメージもあるので使い方による
イメージの実体って何?てなったので調べた
Dockerfileでイメージを構築するときに記述する1行が一つのレイヤーですか?→YES
イメージレイヤーについて考慮する必要があるシーンは具体的にどういった場面がありますか?
→dockerイメージが増えすぎるとパフォーマンスが低下する。イメージレイヤーが増えるほどバラバラの場所にファイルが存在することになり、オーバーヘッドが発生する可能性がある。ただ現在の実装ではそんなに意識することはない。
Dockerの特徴
コンテナの設定をコードベースで管理する
資産を共有する
イメージ作成時の実行と、コンテナ起動時の実行は内容が異なる
差分がなければ処理をスキップする機能(キャッシュの利用)がdockerにあるので、それをうまく利用して毎回実行しなくていいコマンドを省略できる。明示的にコマンドを書き分けるようなことはしない
開発環境のコンテナ化
開発の際の実行環境にDocker を利用する
RailsとかのDBと一緒に起動する必要がある場合はDocker Composeを利用して複数コンテナを一緒に立ち上げる
環境構築がコマンド一発になる
MacやWinなど異なるローカル環境でも同じ開発環境を利用できる
OSのバージョンとかインストールされているソフトウェア、プロジェクト外のリソースとのコンフリクトなどなど
ローカル環境依存の影響を受けないようにできる(独立したプロセスであるため)
デメリット
全ての差分を解消できるわけではない
OSとかミドルウェアは吸収可能だけど、CPUアーキテクチャの環境差分は現状解決できない
M1のCPUは世にある多くのイメージをそのまま使えない
コンパイルする際にCPUアーキテクチャに合わせた形でコンパイルされるため
Docker 特有の問題が発生する可能性
Docker 起因の問題
仮想ネットワーク
ストレージマウント
トラブルシュートが難しくなる(Dockerに詳しくないと解決できなかったりする)
プロダクション環境のコンテナ化
イメージをそのままプロダクションで利用可能
ステージングの環境との差分を無くすことで動作検証の精度が高まる
キャッシュやゴミが溜まったりすることがなくなる
コンテナの中にはキャッシュが溜まるが、コンテナが再作成される(=新たにデプロイされるとか)のたびにキャッシュがリセットされるということ
キャッシュを使った速度向上などとトレードオフでもある
ここで言ってるのは一つのコンテナをずーっと使い続けるということではない
ライブラリアップデート等がやりやすい
実行環境のベースとなるイメージを変更するだけでOK
つまりdockerfileの1行を書き換えるだけ
コンテナを動かすことに特化したプラットフォームを利用できる
AWSのECSとかGCPのCloudRunみたいな環境を使える
コンテナをうまく扱うことに特化している
kubernetesも使える
デメリット
イメージのビルドに時間がかかる
イメージのビルドにはビルドキャッシュを利用して時間短縮を図る
コードをデプロイしてサービスリスタートする時間 < イメージのビルドにかかる時間
監視にコツがいる
永続化されていないファイルが消える
コンテナが再作成されるとコンテナのホスト名が変わる
ホスト名をキーにするのではなく、役割ベースでグループ化するなどの工夫が必要
監視以外にもDcokerならではのお作法が必要な場面がある
トラブルシュートが難しい
アプリケーションをコンテナ化するメリデメまとめ
開発環境、プロダクション環境ともに、スケールメリットが大きい
個人開発、小規模開発だとオーバーテクノロジーになる可能性
個人開発でコンテナ化の恩恵を受けるケース
なるべく費用をかけない
なるべく運用の手間をかけない
=GCPのCloud Runは無料枠が大きいので結構使える
= AWSのLamdaだとコンテナ化したアプリケーションが動かしやすい
デプロイ先の幅が広がる
Vagrantとの使い分け
VagrantはVirtual boxを使って仮想マシンを作る
低レイヤーのアプリケーションの開発ではVagrant使ったりする
プリミティブアプリケーション、ネットワークのアプリケーションなど
プロダクション環境でコンテナ実行するならAWSのECSとkubernatesどちらがいい??
AWSの中だけで済むならECSでOK
コンテナの実行環境だけだったらECSはかなり優秀で使いやすい
AWSの他のアプリケーションとの連携やりやすい
Kubernetesじゃないとダメなことがある場合以外はオーバーテクノロジーになりやすい
専門の知識が必要で運用が大変
オンプレで Kubernetes使ってて連携させる、とかの場合
Amazon Elastic Container Service (ECS) Anywhere は、カスタマー管理のインフラストラクチャでコンテナのワークロードを簡単に実行および管理することを可能にする Amazon ECS の機能です。
演習
docker run -it ubuntu bash
apt install jq
apt install openssl
apt install vim
rootでログインできたのでなんでもできる
code:bash
root@bce8bc0c6f46:/# openssl version
OpenSSL 1.1.1f 31 Mar 2020
root@bce8bc0c6f46:/#
コンテナ壊す→再度起動したら元に戻る
code:bash
root@4824b6ab1ed9:/# rm -rf usr
root@4824b6ab1ed9:/# ls
bash: /usr/bin/ls: No such file or directory
root@4824b6ab1ed9:/# rm -rf var
bash: /usr/bin/rm: No such file or directory
root@4824b6ab1ed9:/#
インストールしたライブラリが消える
code:bash
root@bce8bc0c6f46:/# rm -rf /bin
root@bce8bc0c6f46:/# ls
boot dev etc home lib lib32 lib64 libx32 media mnt opt proc root run sbin srv sys tmp usr var
root@bce8bc0c6f46:/# which vim
bash: /usr/bin/which: /bin/sh: bad interpreter: No such file or directory
root@bce8bc0c6f46:/#
root@bce8bc0c6f46:/home# exit
~/practice ❯❯❯ docker run -it ubuntu bash
root@4824b6ab1ed9:/# ls
bin boot dev etc home lib lib32 lib64 libx32 media mnt opt proc root run sbin srv sys tmp usr var
root@4824b6ab1ed9:/#
root@4824b6ab1ed9:/# openssl version
bash: openssl: command not found
root@4824b6ab1ed9:/#
コンテナないで作成したファイルは再起動したら消える
code:bash
~/practice ❯❯❯ docker run -it ubuntu bash
root@dda6914e52c0:/# echo 'test file' > /mnt/test.txt; ls /mnt/test.txt
/mnt/test.txt
root@dda6914e52c0:/# exit
exit
~/practice ❯❯❯ docker run -it ubuntu bash
root@132eccb066dc:/# ls /mnt/test.txt
ls: cannot access '/mnt/test.txt': No such file or directory
root@132eccb066dc:/#
スペシャルファイルは消せない
デバイスの読み込みのファイルとか
これはLinuxの仕様
コンテナ内のファイルの永続化
code:bash
~/practice ❯❯❯ docker run -it ubuntu bash
root@7fa32fef7bd8:/# exit
~/practice ❯❯❯ docker run -v $PWD:/mnt -it ubuntu bash
root@f158cf71f856:/# echo 'test file' > /mnt/test.txt; ls /mnt/test.txt
/mnt/test.txt
root@f158cf71f856:/# exit
⏎
~/practice ❯❯❯ docker run -v $PWD:/mnt -it ubuntu bash
root@be313dea2cc5:/# ls /mnt/test.txt
/mnt/test.txt
root@be313dea2cc5:/#
root@f158cf71f856:/# exit
# mountされた先のローカルディレクトリにファイルが存在する
~/practice ❯❯❯ ls
go-udemy test.txt vm
~/practice ❯❯❯
プロセス内から外の環境に対してファイルをマウントする
本来見えないはずのプロセスの外にアクセスする、これすごい → これは間違い
ファイルシステムについては別の仕組みを使っている
ホスト→コンテナ内へとアクセスは許可されている(mountしている)
code:bash
~/p/docker-test ❯❯❯ cat Dockerfile
FROM ubuntu
RUN touch /test.txt
~/p/docker-test ❯❯❯
~/p/docker-test ❯❯❯ docker build -t test-image .
+ Building 0.4s (6/6) FINISHED Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them
~/p/docker-test ❯❯❯ docker run -it test-image ls /test.txt
/test.txt
~/p/docker-test ❯❯❯
コマンド解説
FROMで利用するイメージを指定
RUNで実行コマンドを指定
-t test-imageはタグ名の指定
. はイメージを作る場所を指定する(Dockerfile の参照先)
docker run -it イメージ名に続けてコマンドを実行できる
docker for macやdocker for windowsの役割
Macの上でUbuntuが起動できる理由
仮想マシン立ててLinuxを起動できるようにしている
docker社が頑張ってる
コンテナ内のrubyを使って、ローカルのファイルを実行する
code:bash
~/p/docker-test ❯❯❯ cat Dockerfile
FROM ruby:3.1
ADD test.rb /
~/p/docker-test ❯❯❯
~/p/docker-test ❯❯❯ echo 'print("hello")' > test.rb
~/p/docker-test ❯❯❯ docker build -t ruby-test .^C
~/p/docker-test ❯❯❯ vim test.rb
~/p/docker-test ❯❯❯ docker build -t ruby-test .
# 実行結果一部省略
+ Building 20.2s (8/8) FINISHED => internal load build definition from Dockerfile 0.0s => => transferring context: 47B 0.0s
=> 1/2 FROM docker.io/library/ruby:3.1@sha256:32d01e852ad69212a0b83f99296210f11c5b5c932b569684a8948b921f7206 16.1s => => resolve
=> 2/2 ADD test.rb / 0.7s Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them
~/p/docker-test ❯❯❯ docker run -it ruby-test ruby /test.rb
hello
~/p/docker-test ❯❯❯ cat test.rb
print("hello")
~/p/docker-test ❯❯❯
Dockerfileの書き方(公式リファレンス)
Dockerのビルド時にキャッシュされてることが確認できる
Docker は可能な限り 構築キャッシュbuild-cache を使用し、 docker build の処理を著しく高速にします。その場合はコンソール出力に CACHED というメッセージが出ます。(詳細については、 Dockerfile のベストプラクティスガイド を参照ください。)
nginxイメージの起動
code:nginx
~/p/docker-test ❯❯❯ docker run -p 8080:80 -it nginx
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
5eb5b503b376: Pull complete
1ae07ab881bd: Pull complete
78091884b7be: Pull complete
091c283c6a66: Pull complete
55de5851019b: Pull complete
b559bad762be: Pull complete
Digest: sha256:2834dc507516af02784808c5f48b7cbe38b8ed5d0f4837f16e78d00deb7e7767
Status: Downloaded newer image for nginx:latest
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2022/02/26 03:09:21 notice 1#1: using the "epoll" event method 2022/02/26 03:09:21 notice 1#1: nginx/1.21.6 2022/02/26 03:09:21 notice 1#1: built by gcc 10.2.1 20210110 (Debian 10.2.1-6) 2022/02/26 03:09:21 notice 1#1: OS: Linux 5.10.76-linuxkit 2022/02/26 03:09:21 notice 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576 2022/02/26 03:09:21 notice 1#1: start worker processes 2022/02/26 03:09:21 notice 1#1: start worker process 32 2022/02/26 03:09:21 notice 1#1: start worker process 33 2022/02/26 03:09:21 notice 1#1: start worker process 34 2022/02/26 03:09:21 notice 1#1: start worker process 35 172.17.0.1 - - 26/Feb/2022:03:09:44 +0000 "GET / HTTP/1.1" 200 615 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.109 Safari/537.36" "-" 2022/02/26 03:09:44 error 32#32: *1 open() "/usr/share/nginx/html/favicon.ico" failed (2: No such file or directory), client: 172.17.0.1, server: localhost, request: "GET /favicon.ico HTTP/1.1", host: "localhost:8080", referrer: "http://localhost:8080/" https://gyazo.com/9ccdb7bb8b9d1b34a85de014535483d3
できた🎉
docker-composeについて