Docker
Overview
Dockerについてまとめているセクション。
参考
Dockerfile(リフェレンス)
入門Docker
軽量なDockerfileの作り方
Dockerfile ベストプラティクス(かなりすごい)
Dockerセキュリティ(これもLTに入れる)
docker container prune -f;
docker image prune -f;
docker volume prune -f
そもそもコンテナーとは
コンテナーとはアプリケーションの実行環境をパッケージ化し、それをデプロイ、実行するためのテクノロジーのこと。
- アプリケーションコード
- ライブラリ
- プログラミング言語のランタイム
アプリケーションを実行するための依存関係をコンテナーイメージとしてパッケージ化する。
また、パッケージ化されたコンテナーイメージは任意の場所で実行されるコンテナーランタイムによりコンテナーとして実行ができるようになる。
コンテナーを利用することで得られるメリット
可搬性を得ることができる。
※どこでも同じ環境を再現できる
昨今の開発
コンテナーの持つ可搬性によりさまざまなメリットが得られ、ユーザーがよりアプリケーション開発に集中できることから、サーバーレステクノロジーと同様にモダンアプリケーションにおける重要な選択肢の1つとなっています。
Lambdaの方が抽象度高く、多くの作業をAWSにオフロードできる。
Lambdaで要件を満たせない場合にAmazon ECSやAmazon EKSの採用を検討することになる。
AWS Lambda関数の**タイムアウト設定は最大で15分のため、**それ以上の実行時間が想定されるアプリケーションでは採用が難しくなる。
そのような場合、アプリケーションの実行環境としてコンテナーが候補に挙がるため、Amazon ECSやAmazon EKSが選択肢に出てくる。
サーバーレスとコンテナー使い分ける指標
アプリケーション開発により多くの時間や人を投資できる選択肢はどれかという観点で整理する考え方。
コンテナーをアプリケーション実行環境へする場合
Amazon EC2あるいはAWS Fargateが選択肢となる。
Fargateを利用すると、Dockerなどのコンテナランタイムを含むAmazonEC2インスタンスの管理が不要となるため、コンテナワークロードの運用負荷が軽減されます
Docker Linter
DockerfileのLinterとしてhadolintというものがデファクトスタンダードとして存在する。
Volume Trick
まず、node_modulesはDockerイメージにホストからコピーしてはいけません。node_modulesはgitでも無視するはずなので、新しく環境構築する人のディレクトリにはそもそも入ってませんし、イメージをリビルドするときにホストのnode_modulesからイメージ内のnode_modulesが上書きされることも避ける必要があるからです。
Volume Trick
は通常、Docker環境でNode.jsアプリケーションを開発する際に node_modules
ディレクトリを効果的に管理する方法として使用される
1. パフォーマンス向上
ホストマシンとDockerコンテナー間で node_modules
ディレクトリを共有すると、パフォーマンスが低下することがあります。Volumeを使用することで、この問題を回遍することが可能です。
2. 環境の違いの管理
異なるOSや環境で動作させる際に、異なる依存関係やバイナリを必要とするパッケージが存在することがあります。Volumeを使用することで、コンテナー内で専用の node_modules
ディレクトリを保持でき、ホストOSとは異なる環境での依存関係の問題を回避できます。
3. ホストマシンのディスクスペースの節約
node_modules
ディレクトリはしばしば大きく、多くのプロジェクトをホストマシンに保持している場合、ディスクスペースを大量に消費します。Volumeを使用すると、これらのディレクトリをコンテナー化された環境内に保持でき、ホストマシンのディスクスペースを節約できます。
4. 簡単な依存関係の管理
開発中に依存関係を迅速にインストール/アンインストールする必要がある場合、Volumeを使用することで、ホストマシンの影響を受けずにこれを行うことができます。
5. コンテナーの再利用
コンテナーを再起動したり、新しいコンテナーを起動したりする際に、すでにインストールされている依存関係を再利用できます。
これにより、新しいコンテナーの起動時間が短縮されます。
6. ホストとコンテナー間の依存関係の競合を回避
ホストマシンとDockerコンテナーで異なるバージョンの依存関係を使用することが可能。
これにより、ホストとコンテナー間で依存関係の競合が発生するのを避けることができます。
注意: ただし、Volume Trickを使用すると、node_modules
ディレクトリの管理が複雑になる可能性があり、とくに新しい依存関係を追加または削除する際に問題が発生することがあります。また、ボリュームはDockerホストのディスクスペースを使用しますので、大量のデータを保持する長期間稼働するボリュームはディスクスペースを消耗します。このため、定期的なメンテナンスが必要となることもあります。
Docker が軽い方がいい理由
Docker imageの中身を見る(レイヤー)
以下の要望があるときに見られる
作成したイメージがどうなっているかを確認したいとき。
レイヤーについて詳しく見られる。
docker save -o [name].tar [image id]
Docker mysql
dockerでvolumeをマウントした時のファイルowner問題
ホスト側のファイルをコンテナー内で使いたい場合や、逆にコンテナーで作ったファイルにホストからアクセスしたい場合に有用なのだが、ファイルのアクセス権限について考慮すべき点がある。 ちなみにdocker for macで試したところ、上記の問題は起きない。 コンテナー内からはownerがrootとして表示されるが、mac上からは自ユーザーがownerとして表示されている。docker for macの中でうまく解決してくれているようだ。
docker 仕組み
参考URL
Dockerはビルドのステップごとにファイルシステムの変更差分を積み重ねることでイメージを作成する。
先にGemfileをイメージに組み込んでbundle installを実行しておかなければソースコードを変更するたびに毎回bundle installをする必要がある。
# 先にGemfileを転送しbundle installする
COPY --chown=rails Gemfile Gemfile.lock package.json yarn.lock /app/
RUN bundle install
RUN yarn install
上記のような工夫をすることでGemfileの内容に変化がなかった場合は bundle install
の工程までキャッシュを利用することが可能になり2回目以降のビルドが大きく高速化される。
インストールするimageの中を確認する
そのイメージになにが含まれているのか確認する方法
$ docker run -it alpine:3.11
言語のalpineだと/bin/shなどで起動する必用がある。
$ docker run -it alpine:3.11 /bin/sh
docker-composeではない起動方法
- Dockerfileを用意する
- build
Docker コマンド一覧
run imagesからコンテナーを起動する。
exec 起動中のコンテナーに入る
リモートサーバー内のDockerにローカルから接続する
Dockerでもlocalhostでも起動した時に 0.0.0.0
などパブリックドメインで公開すればアクセスできる。
0.0.0.0
Docker セキュリティ
コンテナセキュリティの課題は、ダウンロードしたコンテナイメージが期待通りであるか。 セキュリティと一貫性の観点から期待通りのイメージがダウンロードされることの保証が重要。 Dockerのイメージタグは便利だが常に一貫した特定のイメージを指すとは限らないためSHA-256ハッシュを使ってイメージを識別すること
TODO: これLT アプリケーションがrootで実行されている もしアプリケーションにOSコマンドインジェクションやディレクトリトラバーサルなどの脆弱性があり、それが悪用された場合アプリケーションがroot権限で実行されていると悲惨なことになります
docker security
Docker パーミッション
LinuxではDockerを実行した場合、作成されたファイルの所有権が root
になる(公式はrootで対応するなと言っている)
そのためDockerfileの ADD/COPY
に --chown
オプションができており、それ用のuserを作成するルールになっている。
Dockerfile ---chown 参考URL
Dockerイメージを軽くする
Dockerfile ビルダーパターン
マルチステージビルドとも呼ばれていることがある。 ビルダーパターンなど(FROMが2度現れること)がある。 つまり、xxxパターンを調べて勉強しろ
マルチステージビルド
マルチステージビルドは、Docker17.05以上で利用できる新機能 前のステージでビルドされた成果物をこの新しいステージへコピーする 最終的なイメージでは取り残され最終的なイメージへは保存されない。 ※つまり、TypeScriptをコンパイルするステージ⇨最終的なJSを実行するステージに分けることができる。
COPY --from=0
Docker image削除
containerを削除してからではないとimageが削除できない。
dockerignoreとは
docker buildでimageを作成する際に無視するファイル・ディレクトリを設定できる。 ※mountの場合は無視ができない。
Dockerのマウント種類
参考URL mountディレクトリの恐ろしさ たとえばDockerfile内でCopyをした場合、コピーされるがバインドマウントのためではないため編集しても反映されない。
そのためdocker imageを作成するためだけを意識すること また、COPYでせっかく全部コピーしてもバインドマウントで同じディレクトリを指定した場合にバインドマウントの中身ですべて消される。これが注意!!
alpine linux
alpine linuxは基本 GCC などの C コンパイラが含まれていない(つまり開発ツール)
alpine linuxにyarnいれる python:alpineにCコンパイラをインストール
Docker 参考文献
お前らのDockerfileは重い。 世界一わかりみが深いコンテナー Docker での Node 環境構築 Docker 環境構築best practice
Dockerコンテナー内のアプリケーションport
Dockerコンテナー内のアプリケーションは、デフォルトでネットワークトラフィックを受け入れている。
→http://127.0.0.1:3000
このインターフェースは外部トラフィックを受け入れないため、機能しないのも不思議ではありません。これを機能させるには、nuxtアプリのHOST環境変数を**0.0.0.0(すべてのIPアドレス)**に設定する必要がある。
コンテナーのサーバがlocalhostでlistenしていると、ホストマシンからアクセスした際にエラーが起きることを確認した。 これは、ホストマシンのlocalhostとコンテナーーのlocalhostが異なるため
ホストマシンとcontainerはnamespaceで区切られてい て別のマシンと捉えて構わないため、containerのloopback interfaceにはホストマシンからはアクセスできない。
イメージをビルドするタイミングとは?
- Dockerfileを書き換えた時。
- パッケージ管理を行うファイルを書き換えた時
Dockerを軽くする方法
- RUNはチェーンする(&&)とにかくつなげる。RUN毎にレイヤーが作成されてしまうため(実際これもどうなんだろうと言われている)
- 産業廃棄物(docker build)時に生じた、アプリケーション実行には不要なツールやファイルを削除する
- yumやapt-getのゴミ
- ビルドに使用したソース
- gitですら産業廃棄物
- 成果物を残すことを意識する
- yarn installなどを早めたい