Deployment Concepts and Strategies

 
カテゴリー CI/CD   タグ

基本的なデプロイメント方式

Big Bang Deployment

昔のソフトウェア配布

  • アプリケーションの全体または一部を一度に更新する
  • 典型的なウォーターフォール型開発でのデプロイメント方法
  • ロールバックが不可能または非実用的
  • リリース前に大規模な開発とテストを実施する必要がある
  • クライアント側のインストールを更新するため、クライアント側のアクションが必要
  • デスクトップアプリケーションなどのベンダーパッケージソリューションに向け

Build Deployment

CI/CDパイプラインでビルドしてデプロイする方式

  • CI/CDパイプラインでアプリをビルドしてデプロイする
  • デプロイ時にサービス停止する

Basic Deployment

1つのバージョンでデプロイする方式

  • 全ノードに1バージョンで同時に更新する
  • Simple & Fast
  • ハイリスク
  • 停止が発生する
  • ロールバックが遅い

Multi-Service Deployment

複数のバージョンをデプロイする方式

  • 全ノードに複数バージョンを配置する
  • Simple & Fast
  • Basic Deploymentよりはリスクが低い
  • 停止が発生する
  • ロールバックが遅い

Zero Downtime Deploymentが可能なデプロイメント方式

Rolling Deployment, Rolling Update

インスタンスを順次入れ替えるシンプルな方式。
多くのImmutable Infrastructureの標準の(簡単な)デプロイ方式として実装されている。

  • 全ノードは1バージョン
  • one-by-one(あるいはN batches)で新しいサービスに置き換える
  • Simple
  • ロールバックが比較的簡単
  • 新旧混在するのでアプリケーションやデータベースが混在環境を許容できる必要がある
  • トランザクションの喪失、ログオフされたユーザの考慮が必要

Blue/Green Deployment, Red-Black Deployment, A/B Deployment

平行稼働した新旧インスタンス群を一度に切り替える方式。

  • Blue(Staging)とGreen(Production)の2つの環境を用意し、切り替える
  • ロードバランサーで切り替える
  • 展開が成功した後に旧環境を廃止する方式を一部ベンダーはRed/Black Deploymentと呼称している
  • ダウンタイムなし
  • Simple & Fast
  • ロールバックが早い(Rapid rollback/flip traffick back)
  • 失敗(SPOF or outage)した場合、ロールバックするまで影響は大きい
  • 既存のトランザクションとセッションは失われる
  • データベースの互換性

Canary Deployment, Linear Canary Deployment

平行稼働した新旧インスタンス群を一定割合先行して公開したのちに、残りを一度に切り替える方式。
Linear Canary Deploymentは新しいインスタンス群の割合を順次増加させていく方式。

  • 全ノードは1バージョン
  • 一部ノードを新バージョンにし徐々に割合を増やす
  • 現在、アプリケーション/サービスの展開で一般的な方法
  • 段階的(2%, 10%, 25%, 50%, 75%, 100%.. など)
  • 失敗時のリスクが低い
  • 実行環境を重複して用意する必要がないのでBlue/Greenより安価
  • 高速かつ安全なロールバック
  • スクリプトによるカナリア展開は複雑
  • データベースの互換性

A/B Testing

A/B Testingは行動監視の方式であって、デプロイメント方式ではない。

  • 異なるバージョンを一定期間実験的に本番環境で実行する
  • A/B Testingツールを使用する
  • ユーザトラフィックはルール/統計に基づいて異なるバージョン(実験)ごとにルーティング
  • 実験終了後、最適と判断されたサービスバージョンで更新する
  • 実験による不具合(アプリ、サービス、ユーザエクスペリエンス)
  • ABテストのスクリプトが難しい
  • データベースの互換性

Zero Downtime Deploymentのために考えること

下位互換性のあるデータベーススキーマ / メッセージスキーマ

平行稼働やロールバックのために互換性が必要。

  • アプリケーションのアップグレードからデータベースの移行を切り離すので下位互換性を考えないといけない
  • プロセス間でメッセージが送信されている場合、メッセージスキーマも考慮しなくてはならない
  • 下位互換のない変更を安全に行う方法(ParallelChange/expand and contract

wind-down period

切替タイミングでの稼働中のタスクの問題。

  • アプリケーションが実行時間の長いタスクを処理する場合、これ以上タスクを実行できないようにする

ユーザセッションの損失を軽減する

Immutable Infrastructureとして構成する必要がある。

  • セッションをデータストアに永続化する
  • アプリケーション間でセッションを共有する
  • ステートレスバックエンドにする
  • セッションアフィニティを使用して、すべての新しいセッションをアップグレードされたバックエンドに転送する

ロードバランサーを適切に利用する

接続中のコネクションの排出(Draining)を考慮する必要がある。

  • シャットダウンする前にトラフィックをバックエンドから排出(Draining)する
  • 新しく再起動したバックエンドに適切に再度有効にする

Long live the connection

とくにWebSocketやHTTP long pollingの場合は排出(Draining)のタイムアウトを超え強制終了されるかもしれない。
通知してアプリケーション側で正常な終了プロセスを行う方法もある。

This draining approach works great for the majority of cases. But every once in a while, you need a little more control over the shutdown process — especially when you have long-lived sessions, such as WebSockets or HTTP long polling.
The problem with long-lived WebSocket sessions is that the Application Load Balancer (ALB) starts to forcibly kill all “still active” connections once the draining period has elapsed. By the time the application receives a SIGTERM, the long-lived connections may have already been terminated by the ALB. This makes it impossible to close them gracefully on the application side.
This doesn’t have to be a big problem. The long-lived WebSockets will be closed abnormally — which would lead to 1006 Abnormal Closure code on the server and the client. But that’s all. Clients will reconnect to another healthy task and continue to operate normally.

コメント・シェア

コンテナデザインパターン

 
カテゴリー Container   タグ

Design patterns for container-based distributed systems

オライリー 分散デザインパターン コンテナを使ったスケーラブルなサービスの設計

目次は以下で上述論文と類似している。

  • 第Ⅰ部 シングルノードパターン
    • 2章 サイドカー
    • 3章 アンバサダ
    • 4章 アダプタ
  • 第Ⅱ部 マルチノードパターン
    • 5章 レプリカがロードバランスされたサービス
    • 6章 シャーディングされたサービス
    • 7章 スキャッタ・ギャザー
    • 8章 ファンクションとイベント駆動処理
    • 9章 オーナーシップの選出
  • 第Ⅲ部 バッチ処理パターン
    • 10章 ワークキューシステム
    • 11章 イベント駆動バッチ処理
    • 12章 協調的バッチ処理

Single-container management patterns

従来のコンテナ管理システムの管理インターフェイス(run, pause, stop)では制限が大きかった。コンテナオーケストレーションによってAPI経由で細やかな操作が可能になった。

Upward API

利用者に対して情報を公開するインターフェイス。

  • application-specific monitoring metrics(アプリ固有の監視メトリクス)
  • profiling information of interest to developers(開発者向けのプロファイリング情報)

Downward API

コンテナを制御し、ステートフルなコンテナも適切に管理する。

  • graceful deletion (DockerのSIGTERM→SIGKILLの話)
  • state serialization and recovery (ステートのシリアライゼーションとリカバリ)

Single-node, multi-container application patterns

KubernetesではPods、Nomadではtask groupsと読んでいるコンテナグループのパターン。

サイドカーパターン(Sidecar pattern)

最も一般的なパターン。サイドカー(Sidecar)コンテナはメインコンテナを拡張・強化するためのコンテナ。例えば、メインコンテナがWebサーバでローカルディスク上にログを記録している場合、そのログを収集して永続記憶領域に保存するログセーバー(logsaver)コンテナ。
同じくWebサーバが参照するローカルディスク上のコンテンツをGITリポジトリの変更を検知して更新するコンテンツマネジメントコンテナ。

マルチコンテナ共通のメリットとして以下がある。

  • Webサーバコンテナは安定した低レイテンシの応答を提供しログセーバーコンテナは余ったCPUリソースを使うように構成
  • 異なるコンテナにより別々のプログラミングチームに分けることができる
  • ログセーバーコンテナを他のメインコンテナと組み合わせて使用することができる
  • ログセーバーコンテナがエラーになってもWebサーバコンテナはサービス継続できる(縮退運転が可能)
  • 独立して各機能のアップグレード/ロールバックが可能

アンバサダーパターン(Ambassador pattern)

アンバサダー(Ambassador)コンテナはメインコンテナとの通信を仲介するプロキシとして動作する。
例えば、twemproxyによるアンバサダーを用いることで、アプリケーションはプロキシとのみ通信すればよく、プロキシは複数のMemcachedサーバのシャーディングを行う構成が取れる。

  • localhostの単一サーバに接続することだけ考えればよい
  • スタンドアロンなローカルマシン上のMemcachedを使ってテストすることができる
  • 他のアプリケーションで他の開発言語であっても再利用できる

アダプターパターン(Adapter pattern)

アダプター(Adapter)コンテナは外部からのアクセスに対して、汎用的なインターフェースを持たせることができる。
例えば、モニタリングの共通インターフェースとして、外部に対してメトリックスをエクスポートする。

Multi-node application patterns

マルチノード分散アプリケーション構築のためのパターン。

レプリカロードバランス

シャーディング

ファンクションとイベント駆動処理

散布・収集パターン(Scatter/gather pattern)

並列計算を実行するためのパターン。
典型的には単一リクエストを並列処理し単一応答を返す検索エンジンのようなシステム。
ルートノード(Framework Supplied Root)がユーザ要求を受け、部分計算を行うリーフノード(Developer Supplied Container)で分散処理する。
リーフコンテナの出力を集約するマージコンテナ(Developer Supplied Container)が単一の結果にまとめてルートノードがユーザに返す。

リーダー選出パターン(Leader election pattern)

分散処理のノード間でリーダ選出(典型的なのはレプリケーションにおけるリーダー選出)が必要な場合のパターン。
リーダー選出アルゴリズムのライブラリもあるが、正しく理解して使用することは難しいため、これを抽象化するパターン。
リーダー選出のアルゴリズムは難しいため、アプリケーションにリンクせずに、リーダー選出(Leader election)コンテナとして実装する。
アプリケーションに対してはHTTP APIを利用してリーダ変更を通知する。

Multi-node application patterns - バッチ処理

ワークキューパターン(Work queue pattern)

並列処理可能な大量の処理を実行するためのパターン。
ワークキューのフレームワークは特定の開発言語に依存(例えば、Celery for Python)しているが、これを抽象化して再利用できる。
ユーザからのリクエストは作業コーディネータ(Work Cordinator)コンテナがキュー処理を行い。
作業実行(Work Execution Framework Container)コンテナに振り分けて処理を行う。

イベント駆動バッチ処理

協調的バッチ処理

コメント・シェア

Windowsコンテナ

 
カテゴリー Container Windows   タグ

Windows Container

使用できるWindowsコンテナイメージ

  • Windows
  • Windows Server Core
  • Nano Server
  • Windows 10 IoT Core

Windows Containerの実行条件

Windows Server 2016、またはWindows 10 Anniversaryアップデート(バージョン1607)以降

Windows Containerの互換性

Linuxと異なり積極的にカーネル互換性を維持してこなかったWindowsは制限が多い。

Windows 10 10 月の更新プログラム2018以降、開発/テストのために Windows 10 Enterprise または Professional で windows コンテナーをプロセス分離モードで実行することをユーザーに許可しなくなりました。 詳細については、 FAQを参照してください。Windows Server のコンテナーでは、運用環境で使用されるものと同じカーネルバージョンおよび構成を開発者に提供するために、Windows 10 で既定で Hyper-v 分離を使用します。

Windows Containerチュートリアル

コメント・シェア

Docker Composeチュートリアル

 
カテゴリー Container Tutorial   タグ

docker-compose

公式チュートリアル。python+flaskフロントエンド、redisバックエンドのシンプル構成。

Step 1: Setup

フォルダーdocker_compose作成

1
2
mkdir docker_compose
cd docker_compose

フォルダー内にapp.py作成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import time
import redis
from flask import Flask

app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)

def get_hit_count():
retries = 5
while True:
try:
return cache.incr('hits')
except redis.exceptions.ConnectionError as exc:
if retries == 0:
raise exc
retries -= 1
time.sleep(0.5)

@app.route('/')
def hello():
count = get_hit_count()
return 'Hello World! I have been seen {} times.\n'.format(count)

インストールするpythonモジュールをrequirements.txt

1
2
flask
redis

Step 2: Create a Dockerfile

Dockerの設定ファイルをDockerfileで作成。

1
2
3
4
5
6
7
8
9
FROM python:3.7-alpine
WORKDIR /code
ENV FLASK_APP app.py
ENV FLASK_RUN_HOST 0.0.0.0
RUN apk add --no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
COPY . .
CMD ["flask", "run"]

Step 3: Define services in a Compose file

2つのdockerを起動するdocker-compose.ymlを作成。webredisの2つのDocker Containerを起動する。webはSTEP2のDockerfileを使用してDocker Containerを起動し、port5000で待ち受け、redisはredis:aplineイメージをpullしてカスタマイズなしで使用する。

1
2
3
4
5
6
7
8
version: '3'
services:
web:
build: .
ports:
- "5000:5000"
redis:
image: "redis:alpine"

Step 4: Build and run your app with Compose

docker-compose upで起動する。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
PS > docker-compose up
Building web
Step 1/9 : FROM python:3.7-alpine
3.7-alpine: Pulling from library/python
89d9c30c1d48: Pulling fs layer
89d9c30c1d48: Downloading [> ] 29.23kB/2.7
87MB415eb85a: Downloading [> ] 293.6kB/28.
910c49c00810: Downloading [> ] 3.222kB/301
89d9c30c1d48: Downloading [====> ] 277.6kB/2.7
87MB415eb85a: Downloading [==> ] 1.195MB/28.
910c49c00810: Downloading [=====================> ] 127kB/301
910c49c00810: Downloading [==================================================>] 301.7kB/301
89d9c30c1d48: Downloading [=============> ] 752.3kB/2.7
89d9c30c1d48: Extracting [===========================================> ] 2.425MB/2.78
89d9c30c1d48: Extracting [==================================================>] 2.787MB/2.78
910c49c00810: Extracting [==================================================>] 301.7kB/301.
7efe415eb85a: Pull complete
7d8d53519b81: Extracting [==================================================>] 231B/231B
7d8d53519b81: Extracting [==================================================>] 231B/231B
7d8d53519b81: Pull complete
519124ac136c: Pull complete
Digest: sha256:de9fc5bc46cb1a7e2222b976394ea8aa0290592e3075457d41c5f246f176b1bf
Status: Downloaded newer image for python:3.7-alpine
---> 8922d588eec6
Step 2/9 : WORKDIR /code
---> Running in 9150eb4151ea
Removing intermediate container 9150eb4151ea
---> ecccd64cc137
Step 3/9 : ENV FLASK_APP app.py
---> Running in e3b87df8a938
Removing intermediate container e3b87df8a938
---> 7f7e2af72efa
Step 4/9 : ENV FLASK_RUN_HOST 0.0.0.0
---> Running in 0e4a9910abce
Removing intermediate container 0e4a9910abce
---> c220db73c816
Step 5/9 : RUN apk add --no-cache gcc musl-dev linux-headers
---> Running in 3ac74409efbf
fetch http://dl-cdn.alpinelinux.org/alpine/v3.10/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.10/community/x86_64/APKINDEX.tar.gz
(1/12) Installing binutils (2.32-r0)
(2/12) Installing gmp (6.1.2-r1)
(3/12) Installing isl (0.18-r0)
(4/12) Installing libgomp (8.3.0-r0)
(5/12) Installing libatomic (8.3.0-r0)
(6/12) Installing libgcc (8.3.0-r0)
(7/12) Installing mpfr3 (3.1.5-r1)
(8/12) Installing mpc1 (1.1.0-r0)
(9/12) Installing libstdc++ (8.3.0-r0)
(10/12) Installing gcc (8.3.0-r0)
(11/12) Installing linux-headers (4.19.36-r0)
(12/12) Installing musl-dev (1.1.22-r3)
Executing busybox-1.30.1-r2.trigger
OK: 121 MiB in 47 packages
Removing intermediate container 3ac74409efbf
---> 64589c0f27d3
Step 6/9 : COPY requirements.txt requirements.txt
---> 73cf869e71e5
Step 7/9 : RUN pip install -r requirements.txt
---> Running in 574d2aaab6a8
Collecting flask
Downloading https://files.pythonhosted.org/packages/9b/93/628509b8d5dc749656a9641f4caf13540e2cdec85276964ff8f43bbb1d3b/Flask-1.1.1-py2.py3-none-any.whl (94kB)
Collecting redis
Downloading https://files.pythonhosted.org/packages/32/ae/28613a62eea0d53d3db3147f8715f90da07667e99baeedf1010eb400f8c0/redis-3.3.11-py2.py3-none-any.whl (66kB)
Collecting Werkzeug>=0.15
Downloading https://files.pythonhosted.org/packages/ce/42/3aeda98f96e85fd26180534d36570e4d18108d62ae36f87694b476b83d6f/Werkzeug-0.16.0-py2.py3-none-any.whl (327kB)
Collecting itsdangerous>=0.24
Downloading https://files.pythonhosted.org/packages/76/ae/44b03b253d6fade317f32c24d100b3b35c2239807046a4c953c7b89fa49e/itsdangerous-1.1.0-py2.py3-none-any.whl
Collecting Jinja2>=2.10.1
Downloading https://files.pythonhosted.org/packages/65/e0/eb35e762802015cab1ccee04e8a277b03f1d8e53da3ec3106882ec42558b/Jinja2-2.10.3-py2.py3-none-any.whl (125kB)
Collecting click>=5.1
Downloading https://files.pythonhosted.org/packages/fa/37/45185cb5abbc30d7257104c434fe0b07e5a195a6847506c074527aa599ec/Click-7.0-py2.py3-none-any.whl (81kB)
Collecting MarkupSafe>=0.23
Downloading https://files.pythonhosted.org/packages/b9/2e/64db92e53b86efccfaea71321f597fa2e1b2bd3853d8ce658568f7a13094/MarkupSafe-1.1.1.tar.gz
Building wheels for collected packages: MarkupSafe
Building wheel for MarkupSafe (setup.py): started
Building wheel for MarkupSafe (setup.py): finished with status 'done'
Created wheel for MarkupSafe: filename=MarkupSafe-1.1.1-cp37-cp37m-linux_x86_64.whl size=32314 sha256=64efa0058f83c4e0d8a39fa0d6201593fa7a11bf6596e04606b0e67da2a2d3c5
Stored in directory: /root/.cache/pip/wheels/f2/aa/04/0edf07a1b8a5f5f1aed7580fffb69ce8972edc16a505916a77
Successfully built MarkupSafe
Installing collected packages: Werkzeug, itsdangerous, MarkupSafe, Jinja2, click, flask, redis
Successfully installed Jinja2-2.10.3 MarkupSafe-1.1.1 Werkzeug-0.16.0 click-7.0 flask-1.1.1
itsdangerous-1.1.0 redis-3.3.11
Removing intermediate container 574d2aaab6a8
---> 1bf5991056e4
Step 8/9 : COPY . .
---> a781b9ba80ff
Step 9/9 : CMD ["flask", "run"]
---> Running in b36fae1519a9
Removing intermediate container b36fae1519a9
---> 5b84b8389657
Successfully built 5b84b8389657
Successfully tagged docker_compose_web:latest
WARNING: Image for service web was built because it did not already exist. To rebuild this i
b2eb22a0b7db: Extracting [==================================================>] 1.255kB/1.25
b2eb22a0b7db: Extracting [==================================================>] 1.255kB/1.25
5kBine: Pulling from library/redis
c5ccbdf10203: Pull complete
592c37d15428: Pull complete
b70a614994bf: Downloading [==================================================>] 99B/99B
b70a614994bf: Extracting [==================================================>] 99B/99B
b70a614994bf: Pull complete
60027bdc030c: Pull complete
Digest: sha256:ee13953704783b284c080b5b0abe4620730728054f5c19e9488d7a97ecd312c5
Status: Downloaded newer image for redis:alpine
Creating docker_compose_redis_1 ... done
Creating docker_compose_web_1 ... done
Attaching to docker_compose_redis_1, docker_compose_web_1
redis_1 | 1:C 14 Dec 2019 16:28:27.387 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis_1 | 1:C 14 Dec 2019 16:28:27.387 # Redis version=5.0.7, bits=64, commit=00000000, modified=0, pid=1, just started
redis_1 | 1:C 14 Dec 2019 16:28:27.387 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
redis_1 | 1:M 14 Dec 2019 16:28:27.388 * Running mode=standalone, port=6379.
redis_1 | 1:M 14 Dec 2019 16:28:27.388 # WARNING: The TCP backlog setting of 511 cannot be
enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
redis_1 | 1:M 14 Dec 2019 16:28:27.388 # Server initialized
redis_1 | 1:M 14 Dec 2019 16:28:27.388 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To
fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
redis_1 | 1:M 14 Dec 2019 16:28:27.388 * Ready to accept connections
web_1 | * Serving Flask app "app.py"
web_1 | * Environment: production
web_1 | WARNING: This is a development server. Do not use it in a production deployment.
web_1 | Use a production WSGI server instead.
web_1 | * Debug mode: off
web_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)

起動後、http://127.0.0.1:5000にアクセス。

チュートリアル画面1 width=640

redis(Key-Valueストア)にカウンターが記録されていくため、アクセス毎にカウントアップしていくデモになっている。

Step 5: Edit the Compose file to add a bind mount

docker-compose.ymlを編集して、volumesenvironmentを追加。
volumesでホストのカレントフォルダー(app.pyのあるフォルダー)をcodeというディレクトリ名(Dockerfileでapp.pyを配置するフォルダー)で参照する。
environmentは環境変数FLASK_ENVを設定し、flask runflaskdevelopment modeで動作する。

1
2
3
4
5
6
7
8
9
10
11
12
version: '3'
services:
web:
build: .
ports:
- "5000:5000"
volumes:
- .:/code
environment:
FLASK_ENV: development
redis:
image: "redis:alpine"

Step 6: Re-build and run the app with Compose

docker-compose upでContainerを起動し、app.pyのメッセージを編集する。development modeで動作しているので、デバッグログによってapp.pyの変更が検出されていることを確認できる。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
PS > docker-compose up
Creating network "docker_compose_default" with the default driver

…略…

Attaching to docker_compose_web_1, docker_compose_redis_1
redis_1 | 1:C 14 Dec 2019 18:22:40.379 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis_1 | 1:C 14 Dec 2019 18:22:40.379 # Redis version=5.0.7, bits=64, commit=00000000, modified=0, pid=1, just started
redis_1 | 1:C 14 Dec 2019 18:22:40.379 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
redis_1 | 1:M 14 Dec 2019 18:22:40.379 * Running mode=standalone, port=6379.
redis_1 | 1:M 14 Dec 2019 18:22:40.380 # WARNING: The TCP backlog setting of 511 cannot be
enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
redis_1 | 1:M 14 Dec 2019 18:22:40.380 # Server initialized
redis_1 | 1:M 14 Dec 2019 18:22:40.380 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To
fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
redis_1 | 1:M 14 Dec 2019 18:22:40.380 * Ready to accept connections
web_1 | * Serving Flask app "app.py" (lazy loading)
web_1 | * Environment: development
web_1 | * Debug mode: on
web_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
web_1 | * Restarting with stat
web_1 | * Debugger is active!
web_1 | * Debugger PIN: 318-738-267
web_1 | 172.20.0.1 - - [14/Dec/2019 18:23:32] "GET / HTTP/1.1" 200 -
web_1 | * Detected change in '/code/app.py', reloading
web_1 | * Restarting with stat
web_1 | * Debugger is active!
web_1 | * Debugger PIN: 318-738-267
web_1 | 172.20.0.1 - - [14/Dec/2019 18:24:49] "GET / HTTP/1.1" 200 -

変更後は動的にメッセージが変更されていることがわかる。

チュートリアル画面2 width=640

Step 8: Experiment with some other commands

docker-composeで起動しているContainerの状態はdocker-compose psで表示できる。

1
2
3
4
5
6
PS > docker-compose ps
指定されたパスが見つかりません。
Name Command State Ports
----------------------------------------------------------------------------------------
docker_compose_redis_1 docker-entrypoint.sh redis ... Up 6379/tcp
docker_compose_web_1 flask run Up 0.0.0.0:5000->5000/tcp

docker-composeをバックグラウンドで動作させるのはdocker-compose up -d、停止はdocker-compose stop

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
PS > docker-compose ps
指定されたパスが見つかりません。
Name Command State Ports
------------------------------------------------------------------------
docker_compose_redis_1 docker-entrypoint.sh redis ... Exit 0
docker_compose_web_1 flask run Exit 0
PS > docker-compose up -d
Starting docker_compose_redis_1 ... done
Starting docker_compose_web_1 ... done
PS > docker-compose ps
指定されたパスが見つかりません。
Name Command State Ports
----------------------------------------------------------------------------------------
docker_compose_redis_1 docker-entrypoint.sh redis ... Up 6379/tcp
docker_compose_web_1 flask run Up 0.0.0.0:5000->5000/tcp
PS > docker-compose stop
Stopping docker_compose_web_1 ... done
Stopping docker_compose_redis_1 ... done
PS > docker-compose ps
指定されたパスが見つかりません。
Name Command State Ports
------------------------------------------------------------------------
docker_compose_redis_1 docker-entrypoint.sh redis ... Exit 0
docker_compose_web_1 flask run Exit 0

コンテナイメージを指定して、コマンド実行を行うにはdocker-compose run [コマンド名]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
PS > docker-compose run web env
PATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=0cbfdb243a0c
TERM=xterm
FLASK_ENV=development
LANG=C.UTF-8
GPG_KEY=0D96DF4D4110E5C43FBFB17F2D347EA6AA65421D
PYTHON_VERSION=3.7.5
PYTHON_PIP_VERSION=19.3.1
PYTHON_GET_PIP_URL=https://github.com/pypa/get-pip/raw/ffe826207a010164265d9cc807978e3604d18ca0/get-pip.py
PYTHON_GET_PIP_SHA256=b86f36cc4345ae87bfd4f10ef6b2dbfa7a872fbff70608a1e43944d283fd0eee
FLASK_APP=app.py
FLASK_RUN_HOST=0.0.0.0
HOME=/root
PS > docker-compose run web pip list
Package Version
------------ -------
Click 7.0
Flask 1.1.1
itsdangerous 1.1.0
Jinja2 2.10.3
MarkupSafe 1.1.1
pip 19.3.1
redis 3.3.11
setuptools 41.6.0
Werkzeug 0.16.0
wheel 0.33.6

redisContainerのボリュームを削除する。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
PS > docker volume ls
DRIVER VOLUME NAME
local 7c43ed5a237f7bf1d723c67f649a9beebc963a1cc382296144520266401828ed
local 15ed5c9b93d2d610a40b25269455a56aacf77e7211481820738a0cb696b31119
local 66c0d8f05167232b7ab4760d21450439b95cc1f01fc26a3309e821574f445fd0
local de7a255c91c675252901156114743ef68aa7ef2f7daf82818e3899df7499ee17
PS > docker-compose down --volumes
Removing docker_compose_web_run_276ed55e0300 ... done
Removing docker_compose_web_run_906711b02696 ... done
Removing docker_compose_web_run_39db7500d084 ... done
Removing docker_compose_web_run_ec0d0bdb628d ... done
Removing docker_compose_web_run_54937947aa1f ... done
Removing docker_compose_web_1 ... done
Removing docker_compose_redis_1 ... done
Removing network docker_compose_default
PS > docker volume ls
DRIVER VOLUME NAME
local 15ed5c9b93d2d610a40b25269455a56aacf77e7211481820738a0cb696b31119
local 66c0d8f05167232b7ab4760d21450439b95cc1f01fc26a3309e821574f445fd0
local de7a255c91c675252901156114743ef68aa7ef2f7daf82818e3899df7499ee17

dockerとdocker-compose基本操作

docker-composeで起動したContainerの停止

docker-compose upで起動すると、docker-compose.ymlで定義したContainerがすべて起動された状態になっている。docker-composeで起動したdockerを停止させると(今回はCtrl+Cで停止)すべてのContainerが停止する。

1
2
3
4
5
6
7
8
9
10
11
12
web_1    |  * Environment: production
web_1 | WARNING: This is a development server. Do not use it in a production deployment.
web_1 | Use a production WSGI server instead.
web_1 | * Debug mode: off
web_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
Gracefully stopping... (press Ctrl+C again to force)
Stopping docker_compose_web_1 ... done
Stopping docker_compose_redis_1 ... done
PS > docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7b80daf87099 docker_compose_web "flask run" 29 minutes ago Exited (137) 3 minutes ago docker_compose_web_1
73c9ed48c34a redis:alpine "docker-entrypoint.s…" 29 minutes ago Exited (0) 3 minutes ago docker_compose_redis_1

Containerとイメージの一覧

Dockerはdocker images -aでイメージ一覧を、docker ps -aで停止中のものを含めたContainerの状態を確認できる。

docker-composeDocker HUBから取得したイメージをそのまま使用しているredisredisイメージのみがある。Dockerfileでカスタマイズしたイメージはdocker_compose_webイメージと元にしたpythonイメージがある。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
PS > docker images -a
REPOSITORY TAG IMAGE ID CREATED SIZE
docker_compose_web latest 5b84b8389657 29 seconds ago 213MB
<none> <none> a781b9ba80ff 30 seconds ago 213MB
<none> <none> 1bf5991056e4 30 seconds ago 213MB
<none> <none> 73cf869e71e5 34 seconds ago 202MB
<none> <none> 64589c0f27d3 34 seconds ago 202MB
<none> <none> ecccd64cc137 41 seconds ago 98.4MB
<none> <none> 7f7e2af72efa 41 seconds ago 98.4MB
<none> <none> c220db73c816 41 seconds ago 98.4MB
redis alpine a49ff3e0d85f 3 weeks ago 29.3MB
python 3.7-alpine 8922d588eec6 4 weeks ago 98.4MB
PS > docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7b80daf87099 docker_compose_web "flask run" 30 seconds ago Up 28 seconds 0.0.0.0:5000->5000/tcp docker_compose_web_1
73c9ed48c34a redis:alpine "docker-entrypoint.s…" 30 seconds ago Up 28 seconds 6379/tcp docker_compose_redis_1

docker-composeで制御しているContainerはdocker-compose psで、イメージはdocker-compose imagesで確認できる。

1
2
3
4
5
6
7
8
9
10
11
12
PS > docker-compose ps
指定されたパスが見つかりません。
Name Command State Ports
------------------------------------------------------------------------
docker_compose_redis_1 docker-entrypoint.sh redis ... Exit 0
docker_compose_web_1 flask run Exit 0
PS > docker-compose images
指定されたパスが見つかりません。
Container Repository Tag Image Id Size
-----------------------------------------------------------------------------
docker_compose_redis_1 redis alpine a49ff3e0d85f 27.9 MB
docker_compose_web_1 docker_compose_web latest a460579f2e03 203 MB

起動中のContainerに対するコマンド実行

起動中のContainerのシェルへアクセスするにはdocker exec -it [コンテナ名] [コマンド名]を使う。alpineはbashがないので/bin/ashを指定する。

1
2
3
4
5
6
7
8
9
10
11
12
13
PS > docker-compose up
Creating network "docker_compose_default" with the default driver

…略…

PS > docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ac1ba1951edb redis:alpine "docker-entrypoint.s…" About a minute ago Up 15 seconds 6379/tcp docker_compose_redis_1
6681c0eff91c docker_compose_web "flask run" About a minute ago Up 15 seconds 0.0.0.0:5000->5000/tcp docker_compose_web_1
PS > docker exec -it ac1ba1951edb /bin/ash
/data #
/data # ls
dump.rdb

docker-composeを使う場合はdocker-compose exec [サービス名] [コマンド名]で操作できる

1
2
3
4
5
6
7
8
9
PS > docker-compose exec web ash
/code # ls
Dockerfile app.py requirements.txt
__pycache__ docker-compose.yml
/code # exit
PS > docker-compose exec redis ash
/data # ls
dump.rdb
/data # exit

Containerを起動して一度だけコマンド実行を行う

イメージからContainerを新しく起動する場合はdocker run [イメージ名] [コマンド名]

1
2
3
4
5
6
7
8
9
10
11
PS > docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker_compose_web latest a460579f2e03 About an hour ago 213MB
redis alpine a49ff3e0d85f 3 weeks ago 29.3MB
python 3.7-alpine 8922d588eec6 4 weeks ago 98.4MB
PS > docker run docker_compose_web /bin/ash
PS > docker run -it docker_compose_web /bin/ash
/code # ls
Dockerfile app.py requirements.txt
__pycache__ docker-compose.yml
/code # exit

docker-composeを使う場合はdocker-compose run [サービス名] [コマンド名]で操作できる。

ただし、runで実行した場合、EXPOSEで待ち受けたポートへアクセスできないので注意。

1
2
PS > docker-compose run redis ash
/data # exit

イメージのビルドで失敗し後のゴミ(キャッシュ)を使わないでビルドする

ビルドで失敗したときはキャッシュを使用しないでビルドする必要がある。docker-compose build --no-cacheでキャッシュを使用しないでビルドできる。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
PS > docker-compose up
Creating network "docker_compose_default" with the default driver
Creating docker_compose_web_1 ... error

ERROR: for docker_compose_web_1 Cannot start service web: OCI runtime create failed: container_linux.go:346: starting container process caused "exec: \"flask\": executable file not found in $PATH": unknown

ERROR: for web Cannot start service web: OCI runtime create failed: container_linux.go:346: starting container process caused "exec: \"flask\": executable file not found in $PATH": unknown
ERROR: Encountered errors while bringing up the project.
PS > docker-compose build --no-cache
Building web
Step 1/9 : FROM python:3.7-alpine
---> 8922d588eec6

…略…

---> 84e5766c1f33
Step 9/9 : CMD ["ash", "run"]
---> Running in 66b174736c70
Removing intermediate container 66b174736c70
---> 7f671efb3d2b
Successfully built 7f671efb3d2b

<none>:<none>イメージとシステムのクリーンナップ

初見でわかりにくいのが、REPOSITORY:TAG<none>:<none>イメージの存在。

結論からいえば、The Good <none>:<none>The Bad <none>:<none>がある(参考:What are Docker <none>:<none> images?)。

docker images -aでのみ見えるものがThe Good <none>:<none>でDockerイメージのレイヤー構造に起因したものなのでレイヤー構造を理解しないといけない。The Bad <none>:<none>は他から参照されていないのに存在するゴミでdanglingイメージ(宙ぶらりん?)と呼ばれている。

チュートリアルのビルドログを見ると、イメージの追加削除をくりかえしていることがわかる
最初にpythonイメージがpullされ作成される(これは残っている)

1
2
3
4
5
6
Step 1/9 : FROM python:3.7-alpine

…略…

Status: Downloaded newer image for python:3.7-alpine
---> 8922d588eec6

操作する毎に中間イメージ作成削除を繰り返していく……(これらは残っていない)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
Step 2/9 : WORKDIR /code
---> Running in 9150eb4151ea
Removing intermediate container 9150eb4151ea
---> ecccd64cc137
Step 3/9 : ENV FLASK_APP app.py
---> Running in e3b87df8a938
Removing intermediate container e3b87df8a938
---> 7f7e2af72efa
Step 4/9 : ENV FLASK_RUN_HOST 0.0.0.0
---> Running in 0e4a9910abce
Removing intermediate container 0e4a9910abce
---> c220db73c816
Step 5/9 : RUN apk add --no-cache gcc musl-dev linux-headers
---> Running in 3ac74409efbf
Step 5/9 : RUN apk add --no-cache gcc musl-dev linux-headers
---> Running in 3ac74409efbf

…略…

Removing intermediate container 3ac74409efbf
---> 64589c0f27d3
Step 6/9 : COPY requirements.txt requirements.txt
---> 73cf869e71e5
Step 7/9 : RUN pip install -r requirements.txt
---> Running in 574d2aaab6a8

…略…

Removing intermediate container 574d2aaab6a8
---> 1bf5991056e4
Step 8/9 : COPY . .
---> a781b9ba80ff

最後にdocker_compose_webイメージが生成されて終わる。

1
2
3
4
5
Step 9/9 : CMD ["flask", "run"]
---> Running in b36fae1519a9
Removing intermediate container b36fae1519a9
---> 5b84b8389657
Successfully built 5b84b8389657

danglingイメージdocker image pruneでクリーンナップできるが、これらThe Good <none>:<none>は消えない。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
PS > docker image prune
WARNING! This will remove all dangling images.
Are you sure you want to continue? [y/N] y
Total reclaimed space: 0B
PS > docker images -a
REPOSITORY TAG IMAGE ID CREATED SIZE
docker_compose_web latest 5b84b8389657 29 minutes ago 213MB
<none> <none> a781b9ba80ff 29 minutes ago 213MB
<none> <none> 1bf5991056e4 29 minutes ago 213MB
<none> <none> 73cf869e71e5 29 minutes ago 202MB
<none> <none> 64589c0f27d3 29 minutes ago 202MB
<none> <none> 7f7e2af72efa 29 minutes ago 98.4MB
<none> <none> c220db73c816 29 minutes ago 98.4MB
<none> <none> ecccd64cc137 29 minutes ago 98.4MB
redis alpine a49ff3e0d85f 3 weeks ago 29.3MB
python 3.7-alpine 8922d588eec6 4 weeks ago 98.4MB
PS > docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7b80daf87099 docker_compose_web "flask run" 29 minutes ago Exited (137) 3 minutes ago docker_compose_web_1
73c9ed48c34a redis:alpine "docker-entrypoint.s…" 29 minutes ago Exited (0) 3 minutes ago docker_compose_redis_1

次に停止中のContainerを削除する。削除はdocker container pruneでまとめて削除できる。
そのあとにdocker image pruneでイメージのクリーンナップしてもThe Good <none>:<none>が消えることはない。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
PS > docker container prune
WARNING! This will remove all stopped containers.
Are you sure you want to continue? [y/N] y
Deleted Containers:
73c9ed48c34aaa7cebf06ae40ceca5c8389675e67798868f7df13e7a51e79840

Total reclaimed space: 461kB
PS > docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
PS > docker images -a
REPOSITORY TAG IMAGE ID CREATED SIZE
docker_compose_web latest 5b84b8389657 45 minutes ago 213MB
<none> <none> 1bf5991056e4 45 minutes ago 213MB
<none> <none> a781b9ba80ff 45 minutes ago 213MB
<none> <none> 64589c0f27d3 45 minutes ago 202MB
<none> <none> 73cf869e71e5 45 minutes ago 202MB
<none> <none> c220db73c816 45 minutes ago 98.4MB
<none> <none> ecccd64cc137 45 minutes ago 98.4MB
<none> <none> 7f7e2af72efa 45 minutes ago 98.4MB
redis alpine a49ff3e0d85f 3 weeks ago 29.3MB
python 3.7-alpine 8922d588eec6 4 weeks ago 98.4MB
PS > docker image prune
WARNING! This will remove all dangling images.
Are you sure you want to continue? [y/N] y
Total reclaimed space: 0B
PS > docker images -a
REPOSITORY TAG IMAGE ID CREATED SIZE
docker_compose_web latest 5b84b8389657 46 minutes ago 213MB
<none> <none> a781b9ba80ff 46 minutes ago 213MB
<none> <none> 1bf5991056e4 46 minutes ago 213MB
<none> <none> 73cf869e71e5 46 minutes ago 202MB
<none> <none> 64589c0f27d3 46 minutes ago 202MB
<none> <none> 7f7e2af72efa 46 minutes ago 98.4MB
<none> <none> c220db73c816 46 minutes ago 98.4MB
<none> <none> ecccd64cc137 46 minutes ago 98.4MB
redis alpine a49ff3e0d85f 3 weeks ago 29.3MB
python 3.7-alpine 8922d588eec6 4 weeks ago 98.4MB

Containerから参照されていないイメージはdocker image prune -aでまとめて削除できる。
今度はdocker image prune -aで削除してみる。The Good <none>:<none>も消えるが、参照されていないすべてのものが消える。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
PS > docker image prune -a
WARNING! This will remove all images without at least one container associated to them.
Are you sure you want to continue? [y/N] y
Deleted Images:
untagged: redis:alpine
untagged: redis@sha256:ee13953704783b284c080b5b0abe4620730728054f5c19e9488d7a97ecd312c5
deleted: sha256:a49ff3e0d85f0b60ddf225db3c134ed1735a3385d9cc617457b21875673da2f0
deleted: sha256:f0bc82535d2e3250dad8edf9a8e5ad9f24ee27744393a2c781d36e785498c844
deleted: sha256:1fbf3f39fa220d3b6981fa59b146ee7c5581d39ffb33d1b45685e55bb5cc4c0b
deleted: sha256:48a9a7273f3245a05749ab53f3e5de1721802409fb422419f72c8ca1661869f6
deleted: sha256:e8d9b8d29a84e15b68e4e85f51fe3d50692c5e4cbefa9e7e1005c336734acd55
deleted: sha256:56ee7a6ab270cd80ff8ff38e4a966d311ea53174a60721a62f061efd42c426b3
untagged: docker_compose_web:latest
deleted: sha256:5b84b83896579e86516cdae855c5ad88567bef4086c0866575db89944a23783a
deleted: sha256:560e8806fc52a1cda02805458af3243aa14ec0dfb2068fd401a0e2b14afa8565
deleted: sha256:1bf5991056e4978695a8cf395e398f8655c02d77225f7df3f9b226d176f2291d
deleted: sha256:c9648df40ed18e44c7af492656899b23242a56fd3de3d1e6426f74a5d9c095e3
deleted: sha256:73cf869e71e50d2ef9dda69e8bc23a5275c70194f40534eb831de30fda59eb0e
deleted: sha256:cac7e434b98cf26674aa4e2cb6a17d2be78c22cba899689b5b630774c744d2b8
deleted: sha256:64589c0f27d34132e7eda1aa2012acbf7c8f1d461e382069e452481046fff4e4
deleted: sha256:8df494eabb2663ef5ca5cef25ba7a19941b9ea950b38eb74e2e69ad4b55ef1c1
deleted: sha256:c220db73c81631cb3b2b2ab13cd6d5bf36b26dc4069eba1ffda06ca297c83590
deleted: sha256:7f7e2af72efaa4004d49a92afdec5973ba78036be1528c31eb60fd1ad73beda5
deleted: sha256:ecccd64cc1377d9f940b614c4b28a95eec9c071af90b9a1f921e4e0741ff12dc
deleted: sha256:b2ed5645e18c07e3cf8998599b78707129f5acaf1d599ab25d5d0a0b236a43a3
untagged: python:3.7-alpine
untagged: python@sha256:de9fc5bc46cb1a7e2222b976394ea8aa0290592e3075457d41c5f246f176b1bf
deleted: sha256:8922d588eec695e9ec9e7f7cded1eea0760cb6fe7a8e46092ec12ede474f74e1
deleted: sha256:1aa13cc7d1ee07997279eab07ab1647ee0b3fd360c13486f67034b202100dc29
deleted: sha256:f298bab69f60c995202757bcc8691c1905d4d3a713ba22e96aa7369d53172a7d
deleted: sha256:7cb29a35ad37814ef19699d89f2e461360c010b9acc33a7467490d038f4a007d
deleted: sha256:44a0460612107556df9d2a0a172fae2218986bf496f7cecfdc1354aacca393bc
deleted: sha256:77cae8ab23bf486355d1b3191259705374f4a11d483b24964d2f729dd8c076a0

Total reclaimed space: 236.8MB
PS > docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
PS > docker images -a
REPOSITORY TAG IMAGE ID CREATED SIZE

Containerは停止状態とするが、削除せず存在している状態で、docker image prune -aを試す。Containerからの参照があるので、The Good <none>:<none>を含めすべて残っている。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
PS > docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
497b14b9d4a8 redis:alpine "docker-entrypoint.s…" 33 seconds ago Exited (0) 21 seconds ago docker_compose_redis_1
cb13ceef58a6 docker_compose_web "flask run" 33 seconds ago Exited (137) 11 seconds ago docker_compose_web_1
PS > docker image prune -a
WARNING! This will remove all images without at least one container associated to them.
Are you sure you want to continue? [y/N] y
Deleted Images:
untagged: python:3.7-alpine
untagged: python@sha256:de9fc5bc46cb1a7e2222b976394ea8aa0290592e3075457d41c5f246f176b1bf

Total reclaimed space: 0B
PS > docker images -a
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> 7c27de23c598 About a minute ago 213MB
docker_compose_web latest be361c03fae8 About a minute ago 213MB
<none> <none> 729dfa99b333 About a minute ago 213MB
<none> <none> 55ae4fb24b6c About a minute ago 202MB
<none> <none> 4b9d4224f8df About a minute ago 202MB
<none> <none> 269867bb5613 About a minute ago 98.4MB
<none> <none> 52f58b988872 About a minute ago 98.4MB
<none> <none> 05447f1997bf About a minute ago 98.4MB
redis alpine a49ff3e0d85f 3 weeks ago 29.3MB
<none> <none> 8922d588eec6 4 weeks ago 98.4MB

まっさらにする

Containerは定義ファイルから同じ環境を再構築できるのが利点なので、気軽にまっさらにできる。起動中のContainerも含めてすべてクリーンナップするにはdocker system prune -aを実行する。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
PS > docker images -a
REPOSITORY TAG IMAGE ID CREATED SIZE
docker_compose_web latest be361c03fae8 44 minutes ago 213MB
<none> <none> 7c27de23c598 44 minutes ago 213MB
<none> <none> 729dfa99b333 44 minutes ago 213MB
<none> <none> 55ae4fb24b6c 44 minutes ago 202MB
<none> <none> 4b9d4224f8df 44 minutes ago 202MB
<none> <none> 269867bb5613 44 minutes ago 98.4MB
<none> <none> 05447f1997bf 44 minutes ago 98.4MB
<none> <none> 52f58b988872 44 minutes ago 98.4MB
redis alpine a49ff3e0d85f 3 weeks ago 29.3MB
<none> <none> 8922d588eec6 4 weeks ago 98.4MB
PS > docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
497b14b9d4a8 redis:alpine "docker-entrypoint.s…" 44 minutes ago Exited (0) 43 minutes ago docker_compose_redis_1
cb13ceef58a6 docker_compose_web "flask run" 44 minutes ago Exited (137) 43 minutes ago docker_compose_web_1
PS > docker system prune -a
WARNING! This will remove:
- all stopped containers
- all networks not used by at least one container
- all images without at least one container associated to them
- all build cache

Are you sure you want to continue? [y/N] y
Deleted Containers:
497b14b9d4a834770e6315c849e7d314903134f4063d687f1f82d65eb7765cb6
cb13ceef58a603a3a9511890a092df41e1550a96d95aafa26d8ed3abb2a8dd48

Deleted Networks:
docker_selenium_default
docker_compose_default

Deleted Images:
untagged: docker_compose_web:latest
deleted: sha256:be361c03fae88264f599f6a23996a2de6e2c8a3432d021d0625e018a38d3b0aa
deleted: sha256:7c27de23c5988016c9146a59883033c9dde4e3ebc8eba97138f610ed12421c0c
deleted: sha256:dd362dadecc9aa168ea1fa3995a2fbde78aa73436ea75214a4ccdb18f2bf680c
deleted: sha256:729dfa99b33392c73bae77bc2285c6562fb10ca2726e9040d217c308bff91da8
deleted: sha256:fb5f5130fd197490bd5880b5ee0e4d18a1183243b89c6d0af1924f280bac2eff
deleted: sha256:55ae4fb24b6c06800a5ca9db8967ee6b663a99c827dd5a1310025f7351482ce7
deleted: sha256:7dfcd6f95d80c8ba6d2cdcbdb1b38021daf05004f8dd4666f3bdac3339a8b050
deleted: sha256:461ac6c9722d91ef0f942676fa1508a28e41ef69c59b11c4fc0875860031f912
deleted: sha256:05447f1997bf9712fff19a914e733eda7828acd9495948c66a28bd14436f21c4
deleted: sha256:52f58b988872ed051ff895537b9aed526cf59e9951003994c6ba1037113f22fc
deleted: sha256:dc18d15a91c75af007af66a91e21af80d57239ecb94864c46c6cec3d2f3a80f6
deleted: sha256:8922d588eec695e9ec9e7f7cded1eea0760cb6fe7a8e46092ec12ede474f74e1
deleted: sha256:1aa13cc7d1ee07997279eab07ab1647ee0b3fd360c13486f67034b202100dc29
deleted: sha256:f298bab69f60c995202757bcc8691c1905d4d3a713ba22e96aa7369d53172a7d
deleted: sha256:7cb29a35ad37814ef19699d89f2e461360c010b9acc33a7467490d038f4a007d
deleted: sha256:44a0460612107556df9d2a0a172fae2218986bf496f7cecfdc1354aacca393bc
untagged: redis:alpine
untagged: redis@sha256:ee13953704783b284c080b5b0abe4620730728054f5c19e9488d7a97ecd312c5
deleted: sha256:a49ff3e0d85f0b60ddf225db3c134ed1735a3385d9cc617457b21875673da2f0
deleted: sha256:f0bc82535d2e3250dad8edf9a8e5ad9f24ee27744393a2c781d36e785498c844
deleted: sha256:1fbf3f39fa220d3b6981fa59b146ee7c5581d39ffb33d1b45685e55bb5cc4c0b
deleted: sha256:48a9a7273f3245a05749ab53f3e5de1721802409fb422419f72c8ca1661869f6
deleted: sha256:e8d9b8d29a84e15b68e4e85f51fe3d50692c5e4cbefa9e7e1005c336734acd55
deleted: sha256:56ee7a6ab270cd80ff8ff38e4a966d311ea53174a60721a62f061efd42c426b3
deleted: sha256:77cae8ab23bf486355d1b3191259705374f4a11d483b24964d2f729dd8c076a0

Total reclaimed space: 237.4MB
PS > docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
PS > docker images -a
REPOSITORY TAG IMAGE ID CREATED SIZE

コメント・シェア

Ubuntu18のアップデートを自動更新にする

 
カテゴリー Linux   タグ

自動セキュリティ更新

1
2
3
4
5
6
 * Canonical Livepatch is available for installation.
- Reduce system reboots and improve kernel security. Activate at:
https://ubuntu.com/livepatch

200 個のパッケージがアップデート可能です。
105 個のアップデートはセキュリティアップデートです。

apt updates && apt upgrades -yを実行しないで自動的にアップデートを適用する

unattended-upgradesを使った自動更新

unattended-upgradesをインストール

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
root@bash # apt install unattended-upgrades
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています
状態情報を読み取っています... 完了
以下のパッケージが自動でインストールされましたが、もう必要とされていません:
gconf-service gconf-service-backend gconf2-common libgconf-2-4 libllvm6.0
libllvm7 linux-headers-4.15.0-38 linux-headers-4.15.0-38-generic
linux-headers-4.15.0-39 linux-headers-4.15.0-39-generic
linux-headers-4.15.0-42 linux-headers-4.15.0-42-generic
linux-headers-4.15.0-43 linux-headers-4.15.0-43-generic

…略…

unattended-upgrades (1.1ubuntu1.18.04.13) で (1.1ubuntu1.18.04.11 に) 上書き展開しています ...
ureadahead (0.100.0-21) のトリガを処理しています ...
systemd (237-3ubuntu10.24) のトリガを処理しています ...
unattended-upgrades (1.1ubuntu1.18.04.13) を設定しています ...
man-db (2.8.3-2ubuntu0.1) のトリガを処理しています ...
root@bash #

unattended-upgradesを有効化

1
2
3
root@bash # dpkg-reconfigure -plow unattended-upgrades

Creating config file /etc/apt/apt.conf.d/20auto-upgrades with new version

以下の画面で有効を選択。

unattended-upgrades width=480

unattended-upgrades width=480

自動更新設定(20auto-upgrades)のカスタマイズ

20auto-upgrades(/etc/apt/apt.conf.d/20auto-upgrades)の設定

1
2
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";

以下の内容に変更する

1
2
3
4
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Download-Upgradeable-Packages "1";
APT::Periodic::AutocleanInterval "7";
APT::Periodic::Unattended-Upgrade "1";
パラメーター 内容
APT::Periodic::Update-Package-Lists パッケージリストの更新頻度 日数
APT::Periodic::Download-Upgradeable-Packages パッケージをダウンロードする頻度 日数
APT::Periodic::AutocleanInterval 古いパッケージをAPTキャッシュから削除する(apt autoclean)頻度 日数
APT::Periodic::Unattended-Upgrade unattended-upgradeの有効化 1:有効、0:無効

自動更新設定(50auto-upgrades)のカスタマイズ

50auto-upgrades(/etc/apt/apt.conf.d/50auto-upgrades)で更新時の動作をカスタマイズ
多くの設定項目がコメントアウトされているので、必要項目を有効化していく。

更新対象のパッケージ

通常のアップデートもセキュリティアップデートも更新する

  • "${distro_id}:${distro_codename}-updates";通常のアップデート
  • "${distro_id}:${distro_codename}-security"セキュリティアップデート
1
2
3
4
5
6
7
8
9
10
11
12
Unattended-Upgrade::Allowed-Origins {
"${distro_id}:${distro_codename}";
"${distro_id}:${distro_codename}-security";
// Extended Security Maintenance; doesn't necessarily exist for
// every release and this system may not have it installed, but if
// available, the policy for updates is such that unattended-upgrades
// should also install from here by default.
"${distro_id}ESM:${distro_codename}";
"${distro_id}:${distro_codename}-updates";
// "${distro_id}:${distro_codename}-proposed";
// "${distro_id}:${distro_codename}-backports";
};

使用していないパッケージを自動的に削除する

使用していないカーネルパッケージや依存関係のパッケージを自動削除する

  • Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
  • Unattended-Upgrade::Remove-Unused-Dependencies "true";

自動的にシステムを再起動する

自動的にシステムを再起動(21:00)する

  • Unattended-Upgrade::Automatic-Reboot "true";
  • Unattended-Upgrade::Automatic-Reboot-Time "21:00";

/etc/apt/apt.conf.d/50unattended-upgrades (default)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
// Automatically upgrade packages from these (origin:archive) pairs
//
// Note that in Ubuntu security updates may pull in new dependencies
// from non-security sources (e.g. chromium). By allowing the release
// pocket these get automatically pulled in.
Unattended-Upgrade::Allowed-Origins {
"${distro_id}:${distro_codename}";
"${distro_id}:${distro_codename}-security";
// Extended Security Maintenance; doesn't necessarily exist for
// every release and this system may not have it installed, but if
// available, the policy for updates is such that unattended-upgrades
// should also install from here by default.
"${distro_id}ESM:${distro_codename}";
// "${distro_id}:${distro_codename}-updates";
// "${distro_id}:${distro_codename}-proposed";
// "${distro_id}:${distro_codename}-backports";
};

// List of packages to not update (regexp are supported)
Unattended-Upgrade::Package-Blacklist {
// "vim";
// "libc6";
// "libc6-dev";
// "libc6-i686";
};

// This option will controls whether the development release of Ubuntu will be
// upgraded automatically.
Unattended-Upgrade::DevRelease "false";

// This option allows you to control if on a unclean dpkg exit
// unattended-upgrades will automatically run
// dpkg --force-confold --configure -a
// The default is true, to ensure updates keep getting installed
//Unattended-Upgrade::AutoFixInterruptedDpkg "false";

// Split the upgrade into the smallest possible chunks so that
// they can be interrupted with SIGTERM. This makes the upgrade
// a bit slower but it has the benefit that shutdown while a upgrade
// is running is possible (with a small delay)
//Unattended-Upgrade::MinimalSteps "false";

// Install all unattended-upgrades when the machine is shutting down
// instead of doing it in the background while the machine is running
// This will (obviously) make shutdown slower
//Unattended-Upgrade::InstallOnShutdown "true";

// Send email to this address for problems or packages upgrades
// If empty or unset then no email is sent, make sure that you
// have a working mail setup on your system. A package that provides
// 'mailx' must be installed. E.g. "user@example.com"
//Unattended-Upgrade::Mail "root";

// Set this value to "true" to get emails only on errors. Default
// is to always send a mail if Unattended-Upgrade::Mail is set
//Unattended-Upgrade::MailOnlyOnError "true";

// Remove unused automatically installed kernel-related packages
// (kernel images, kernel headers and kernel version locked tools).
//Unattended-Upgrade::Remove-Unused-Kernel-Packages "false";

// Do automatic removal of new unused dependencies after the upgrade
// (equivalent to apt-get autoremove)
//Unattended-Upgrade::Remove-Unused-Dependencies "false";

// Automatically reboot *WITHOUT CONFIRMATION*
// if the file /var/run/reboot-required is found after the upgrade
//Unattended-Upgrade::Automatic-Reboot "false";

// If automatic reboot is enabled and needed, reboot at the specific
// time instead of immediately
// Default: "now"
//Unattended-Upgrade::Automatic-Reboot-Time "02:00";

// Use apt bandwidth limit feature, this example limits the download
// speed to 70kb/sec
//Acquire::http::Dl-Limit "70";

// Enable logging to syslog. Default is False
// Unattended-Upgrade::SyslogEnable "false";

// Specify syslog facility. Default is daemon
// Unattended-Upgrade::SyslogFacility "daemon";

// Download and install upgrades only on AC power
// (i.e. skip or gracefully stop updates on battery)
// Unattended-Upgrade::OnlyOnACPower "true";

// Download and install upgrades only on non-metered connection
// (i.e. skip or gracefully stop updates on a metered connection)
// Unattended-Upgrade::Skip-Updates-On-Metered-Connections "true";

設定変更後の動作確認

cronによる定期実行を待たなくてもunattended-upgrades --dry-run --debugで即時実行できる

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
root@bash # unattended-upgrades --dry-run --debug
初期状態でブラックリストにあるパッケージ:
初期状態でホワイトリストにあるパッケージ:
自動アップグレードスクリプトを開始します
許可されているパッケージ導入元: o=Ubuntu,a=bionic, o=Ubuntu,a=bionic-security, o=UbuntuESM,a=bionic, o=Ubuntu,a=bionic-updates
Using (^linux-image-[0-9]+\.[0-9\.]+-.*|^linux-headers-[0-9]+\.[0-9\.]+-.*|^linu

…略…

ubuntu-server
ubuntu-standard
udev
util-linux
uuid-runtime
wpasupplicant
xkb-data
60% [us.archive.ubuntu.com へ接続しています]
60% [us.archive.ubuntu.com (91.189.91.23) へ接続しています]
60% [ヘッダの待機中です]
Get:1 http://us.archive.ubuntu.com/ubuntu bionic-updates/main amd64 base-files amd64 10.1ubuntu2.7 [60.3 kB]

…略…

conffile line: /etc/wpa_supplicant/ifupdown.sh 4c82dbf7e1d8c5ddd70e40b9665cfeee
current md5: 4c82dbf7e1d8c5ddd70e40b9665cfeee
blacklist: []
whitelist: []
Removing unused kernel packages: linux-headers-4.15.0-42-generic linux-modules-extra-4.15.0-43-generic

…略…

marking linux-image-4.15.0-43-generic for removal
marking linux-image-4.15.0-38-generic for removal
Packages that were successfully auto-removed:
Packages that are kept back:
Option --dry-run given, *not* performing real actions

…略…

Writing dpkg log to /var/log/unattended-upgrades/unattended-upgrades-dpkg.log

…略…

すべてのアップグレードがインストールされました

…略…

marking linux-image-4.15.0-38-generic for removal
Packages that were successfully auto-removed:
Packages that are kept back:
InstCount=0 DelCount=0 BrokenCount=0

参考

コメント・シェア

クラウドネイティブ

 
カテゴリー Cloud   タグ

Cloud native computing from wikipedia

Cloud native computing is an approach in software development that utilizes cloud computing to its fullest due to its use of an open source software stack to deploy applications as microservices.[1][2] Typically, cloud native applications are built as a set of microservices that run in Docker containers, orchestrated in Kubernetes and managed and deployed using DevOps and Git Ops workflows.[3] The advantage of using Docker containers is the ability to package all software needed to execute into one executable package. The container runs in a virtualized environment, which isolates the contained application from its environment.

キーワードとしては以下が挙げられている

  • Microservices
  • Docker
  • Kubernetes
  • DevOps/GitOps

Cloud Native Computing Foundation (CNCF)

Cloud native technologies empower organizations to build and run scalable applications in modern, dynamic environments such as public, private, and hybrid clouds.
Containers, service meshes, microservices, immutable infrastructure, and declarative APIs exemplify this approach.

Cloud Native Application Architecture

-WalmartLabs techblog Cloud Native Application Architecture

以下が挙げられている

Cloud Native Design Principles(クラウドネイティブデザイン原則)として以下の項目が挙げられている。

  • Designed As Loosely Coupled Microservices(疎結合のマイクロサービスとしてデザイン)
  • Developed With Best-of-breed Languages And Frameworks(適切な言語とフレームワークで開発)
  • Centred Around APIs For Interaction And Collaboration(インタラクションとコラボレーションのためのAPI)
  • Stateless And Massively Scalable(ステートレスで非常にスケーラブル)
  • Resiliency At The Core Of the Architecture(アーキテクチャの中核となる回復性)
  • Packaged As Lightweight Containers And Orchestrated(コンテナ化/コンテナオーケストレーション)
  • Agile DevOps & Automation Using CI/CD(CI/CDによるアジャイルDevOpsと自動化)

some of the strategies for implementing resiliency(回復性を高める戦略)として以下が挙げられている。

  • Retry transient failures(リトライ)
  • Load balance across instances(負荷分散)
  • Degrade gracefully(適切な縮退運転)
  • Throttle high-volume tenants/users(スロットリング)
  • Use a circuit breaker(サーキットブレーカー)
  • Apply compensating transactions(補償トランザクションの適用)

What is Cloud Natvie from Software Circus 2016

Lesson Larntとして以下を挙げている

  • Cloud Natvie needs good tools(クラウドネイティブは良いツールが必要)
  • the infrastructure has to be boring(インフラは退屈でなくては)
  • We need good PATTERNS(良いパターンが必要)
    • Microservices (and Microliths)
    • Cattle not Pets
    • Observability and Control baked in Traffic Patterns (Blue/Green, Canary, smart routing & load balancing …)

PATTERNSは何か?

  • Availability - Microservices
  • Automation - Deployment & Management
  • Acceleration - CI/CD & OODA
  • Anywhere - Containers are portable

コメント・シェア

TerattermのPortforwarding

Portforwardingは設定 -> SSH転送以下で設定

SSLトンネル経由で遠隔ネットワークにリモートデスクトップ接続

  1. 遠隔ネットワークに参加しているホストにSSH接続できる
  2. 遠隔のPCでリモートデスクトップが使える
  3. Teratermでポートフォワーディングを設定する
  4. TeratermでSSH接続
  5. リモートデスクトップクライアントでlocalhostの指定ポートに接続
設定項目 このケースでの意味
ローカルポート localhostの指定ポート
リモート側ホスト リモートデスクトップで接続するPC
ポート PCのリモートデスクトップポート
リッスン 設定なし

リモートデスクトップ設定

リモートデスクトップ width=480

リモートデスクトップ width=480

Terattermのポートフォワーディング設定

Teraterm SSHポート転送 width=480

Teraterm SSHポート転送 width=480

コメント・シェア

Visual Studio Code Remote-Developmentのインストール

  • Remote SSHRemote Containersが含まれている

RemoteDevelopment width=640

RemoteDevelopment width=640

Visual Studio Code Remote-Containers

Remote-ContainersでContainerを起動する

ローカルのdocker-compose.ymlのフォルダーを開いた状態

VSCodeでContainerを開く1 width=640

Remote-Containersで開く。
左下の><マークからコマンドパレットを開き、Remote-Containers: Open Folder in Container ...を選択

VSCodeでContainerを開く2 width=640

**How would you like to create your container configuraion ?**に対し、From a predefined container configuration definition ...を選択

VSCodeでContainerを開く3 width=640

Select a serviceに対して、docker-compose.ymlで定義したサービス名を選択(ここではweb)

VSCodeでContainerを開く4 width=640

.devcontainerというフォルダーが作成され、設定ファイル等が生成される。

VSCodeでContainerを開く5 width=640

VSCodeでContainerを開く6 width=640

docker-composeコマンドで起動した場合とVisuaStudioCodeでの動作の違い

docker-composeで起動した場合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
PS > docker-compose up -d

…略…

Creating docker_compose_redis_1 ... done
Creating docker_compose_web_1 ... done
PS > docker images -a
REPOSITORY TAG IMAGE ID CREATED SIZE
docker_compose_web latest 76509309325d 14 seconds ago 213MB
<none> <none> 5b6b84fd1be8 15 seconds ago 213MB
<none> <none> f5dbdf087e9b 15 seconds ago 213MB
<none> <none> c842dd8db35b 19 seconds ago 202MB
<none> <none> a1924e4016d1 20 seconds ago 202MB
<none> <none> 55c33e5cf06c 26 seconds ago 98.4MB
<none> <none> c04b6508484b 26 seconds ago 98.4MB
<none> <none> bd8c16c6f245 26 seconds ago 98.4MB
redis alpine a49ff3e0d85f 3 weeks ago 29.3MB
python 3.7-alpine 8922d588eec6 4 weeks ago 98.4MB
PS > docker-compose ps
指定されたパスが見つかりません。
Name Command State Ports
----------------------------------------------------------------------------------------
docker_compose_redis_1 docker-entrypoint.sh redis ... Up 6379/tcp
docker_compose_web_1 flask run Up 0.0.0.0:5000->5000/tcp
PS > docker-compose stop
Stopping docker_compose_redis_1 ... done
Stopping docker_compose_web_1 ... done
PS > docker-compose ps
指定されたパスが見つかりません。
Name Command State Ports
------------------------------------------------------------------------
docker_compose_redis_1 docker-entrypoint.sh redis ... Exit 0
docker_compose_web_1 flask run Exit 0

Visual Studio CodeのRemoteContainerで開いた場合

指定したサービス名(今回はweb)のContainerのコマンドが置き換えられている。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
PS > docker-compose ps
指定されたパスが見つかりません。
Name Command State Ports
----------------------------------------------------------------------------------------
docker_compose_redis_1 docker-entrypoint.sh redis ... Up 6379/tcp
docker_compose_web_1 /bin/sh -c while sleep 100 ... Up 0.0.0.0:5000->5000/tcp
PS > docker-compose images
指定されたパスが見つかりません。
Container Repository Tag Image Id Size
-----------------------------------------------------------------------------
docker_compose_redis_1 redis alpine a49ff3e0d85f 27.9 MB
docker_compose_web_1 docker_compose_web latest 76509309325d 203 MB
PS > docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0251a181bf08 docker_compose_web "/bin/sh -c 'while s…" About a minute ago Up About a minute 0.0.0.0:5000->5000/tcp docker_compose_web_1
189be0953add redis:alpine "docker-entrypoint.s…" 6 minutes ago Up About a minute 6379/tcp docker_compose_redis_1
PS > docker images -a
REPOSITORY TAG IMAGE ID CREATED SIZE
docker_compose_web latest 76509309325d 6 minutes ago 213MB
<none> <none> f5dbdf087e9b 6 minutes ago 213MB
<none> <none> 5b6b84fd1be8 6 minutes ago 213MB
<none> <none> c842dd8db35b 6 minutes ago 202MB
<none> <none> a1924e4016d1 6 minutes ago 202MB
<none> <none> bd8c16c6f245 7 minutes ago 98.4MB
<none> <none> 55c33e5cf06c 7 minutes ago 98.4MB
<none> <none> c04b6508484b 7 minutes ago 98.4MB
redis alpine a49ff3e0d85f 3 weeks ago 29.3MB
python 3.7-alpine 8922d588eec6 4 weeks ago 98.4MB

Remote-ContainersでContainerでの開発

Remote-Containersの基本的な動作

app.pyを編集して、flask runを起動すると新しいアプリで実行できる。

.devcontainerフォルダーには開発用のdocker-compose.ymlが生成され、元のdocker-compose.ymlの設定をオーバーライドする設定が行われている。

  • 開いたローカルホスト側のフォルダーをContainer側のworkspaceディレクトリでマウント
  • commandで指定されたコマンドを/bin/sh -c "while sleep 1000; do :; done"に置き換える

VSCodeでContainerを開いた状態 width=640

拡張機能(Extention)のインストール

対象のContainerで使用する開発言語等の拡張機能は通常Installという表記だが、Install on Dev Container: Existing Docker Compose...という表記となっていて、Container側にインストールされる(Remote-SSHと同様)。

VSCode Remote-Containerへの拡張機能インストール width=640

.devcontainerフォルダーにあるdevcontainer.jsonはVisual Studio Codeの拡張機能を自動インストールする設定がある。
Pythonを使用するなら、ms-python.ptyhonがIDになる。

以下はpython開発で使用する**Python Extension Pack(donjayamanne.python-extension-pack)Docker(ms-azuretools.vscode-docker)**の場合。

1
2
3
4
"extensions": [
"donjayamanne.python-extension-pack",
"ms-azuretools.vscode-docker"
]

docker-compose.yml.devcontainersの変更が検知されるとRebuildをするように促される。
Rebuildを実行すると、extentionsで指定した拡張機能がインストールされた状態になっている。

alter_message width=640

コメント・シェア

Dockerコンテナ

 
カテゴリー Container   タグ

Dockerアーキテクチャ

役割はThe Docker clientにあたるdockerコマンドなどからREST APIを介してThe Docker daemonを操作する。
The Docker daemonはLinuxホスト上で動作して、**Docker objects(ImagesとContainers)**をを制御している。

Containersは実行インスタンスで実行時にコマンド1つを実行し、実行終了すれば終了する。
永続ボリュームを持つことができるが、持たないのが基本(Immutable Infrastructure)。

ImagesContainerを作るためのテンプレートイメージに当たる。
Dockerfileを使用して新しいImagesを作成する。このコードのみで同じ環境を再構築できるので、Imagesを維持している必要はない。

ImagesDocker registriesで共有される。
利用者はDocker registriesからImagesを取得(docker pull)してカスタマイズするDockerfileを作成し、自分のコンテナイメージを作成する。
Docker registriesにImagesを公開(docker push)することもできるが有料。

Docker Containerの互換性

コンテナイメージがどこでも動作するのは、LinuxのKernelの互換性に依存している。カーベルバージョンが異なってもABI(Application Binary Interface) の互換性によって互換性が維持されているので動作する。CPUアーキテクチャの違いは吸収されない。

The underlying technology

Namespaces

ワークスペースを分離(isolate)する。
Dockerエンジンが以下のnamespacesを使用する。

  • The pid namespace: Process isolation (PID: Process ID).
  • The net namespace: Managing network interfaces (NET: Networking).
  • The ipc namespace: Managing access to IPC resources (IPC: InterProcess Communication).
  • The mnt namespace: Managing filesystem mount points (MNT: Mount).
  • The uts namespace: Isolating kernel and version identifiers. (UTS: Unix Timesharing System).

Control groups (cgroup)

リソース制御を行う。

Union file systems

UnionFSは複数のディクスレイヤーを重ねて1つにみせる。
自レイヤーにないファイルはCopy on Writeで対応する(Solaris ZFSなどと同じ)。

ContainerImage format

Dockerイメージはlibcontainerという形式のイメージ。

2017年7月Open Containers InitiativeがOCIイメージ仕様を策定したが、Dockerfileの構文・命令が標準化されたわけではない。

Dockerイメージの作成

Define a container with Dockerfile

Dockerfileを定義し、コンテナイメージを作成する。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Use the official image as a parent image.
FROM node:current-slim

# Set the working directory.
WORKDIR /usr/src/app

# Copy the file from your host to your current location.
COPY package.json .

# Run the command inside your image filesystem.
RUN npm install

# Inform Docker that the container is listening on the specified port at runtime.
EXPOSE 8080

# Run the specified command within the container.
CMD [ "npm", "start" ]

# Copy the rest of your app's source code from your host to your image filesystem.
COPY . .

Dockerfileベストプラクティス

推奨項目を抜粋

  • Containerはエフェメラルであるべき

  • .dockerignoreファイルを使う

  • 不要なパッケージのインストールを避ける

  • Container毎に1つのプロセスだけ実行

    • 複数のContainerに分離することは、水平スケールやContainerの再利用を簡単にする
    • サービスとサービスに依存関係がある場合は、Containerのリンクを使う
  • レイヤーの数を最小に

  • 複数行の引数

    • 引数をアルファベット順にする(重複チェックなどで見やすさ)
    • バックスラッシュの前に空白を入れる
  • 構築キャッシュ

    • Dockerfileの指定した各命令を順番に実行
    • 既存のイメージがつかれば使用される
  • Dockerfile を書くためのベストプラクティス解説編

  • Dockerfileを改善するためのBest Practice 2019年版

Docker関連ツール

dockerコマンド

docker-compose

もともとFIGというツールだったが、2014年にDocker社によって買収され、docke-composeとなった。設定ファイルdocker-compose.ymlで構成を記述して、複数のContainerを管理する。

Docker Desktop for Windows

docker-composeを含めた統合環境としてインストールされる。
Docker Desktop for WindowsはWindowsの機能のHyper-Vを使用したLinux環境を介して利用することになる。

Docker Desktop for Mac

おまけのリンク

コメント・シェア

Docker for Windows

 
カテゴリー Container Windows   タグ

Docker for Windowsのインストール

docker.comからダウンロードする。
ダウンロードにはDockerのアカウントが必要。64bit環境のみしか実行できない。

Dockerインストール1 width=480

Dockerインストール2 width=480

Dockerインストール3 width=480

Windowsの機能でHyper-Vが有効化されていない場合、インストールの中で有効化される。

Dockerインストール4 width=480

Dockerインストール5 width=480

Dockerインストール6 width=480

dockerアカウントでログインする。

Dockerインストール7 width=480

共有ドライブを選択する。

Dockerインストール8 width=480

Dockerの起動

1
2
PS > docker --version
Docker version 19.03.5, build 633a0ea

Dockerの起動(CentOS7)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
PS > docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
PS > docker run -it -d --name centos7 centos:centos7
Unable to find image 'centos:centos7' locally
centos7: Pulling from library/centos
ab5ef0e58194: Pull complete
Digest: sha256:4a701376d03f6b39b8c2a8f4a8e499441b0d567f9ab9d58e4991de4472fb813c
Status: Downloaded newer image for centos:centos7
8679da923e5789e8f379451f8f3a17b74f5dc0ba5f9183be16db19807410231a
PS >
PS > docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8679da923e57 centos:centos7 "/bin/bash" 8 seconds ago Up 7 seconds centos7
PS > docker exec -it centos7 /bin/bash
[root@8679da923e57 /]# ls -al
total 64
drwxr-xr-x 1 root root 4096 Dec 10 12:48 .
drwxr-xr-x 1 root root 4096 Dec 10 12:48 ..
-rwxr-xr-x 1 root root 0 Dec 10 12:48 .dockerenv
-rw-r--r-- 1 root root 12123 Oct 1 01:16 anaconda-post.log
lrwxrwxrwx 1 root root 7 Oct 1 01:15 bin -> usr/bin
drwxr-xr-x 5 root root 360 Dec 10 12:48 dev
drwxr-xr-x 1 root root 4096 Dec 10 12:48 etc
drwxr-xr-x 2 root root 4096 Apr 11 2018 home
lrwxrwxrwx 1 root root 7 Oct 1 01:15 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Oct 1 01:15 lib64 -> usr/lib64
drwxr-xr-x 2 root root 4096 Apr 11 2018 media
drwxr-xr-x 2 root root 4096 Apr 11 2018 mnt
drwxr-xr-x 2 root root 4096 Apr 11 2018 opt
dr-xr-xr-x 142 root root 0 Dec 10 12:48 proc
dr-xr-x--- 2 root root 4096 Oct 1 01:16 root
drwxr-xr-x 11 root root 4096 Oct 1 01:16 run
lrwxrwxrwx 1 root root 8 Oct 1 01:15 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 Apr 11 2018 srv
dr-xr-xr-x 13 root root 0 Dec 10 12:48 sys
drwxrwxrwt 7 root root 4096 Oct 1 01:16 tmp
drwxr-xr-x 13 root root 4096 Oct 1 01:15 usr
drwxr-xr-x 18 root root 4096 Oct 1 01:15 var
[root@8679da923e57 /]# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 12:48 pts/0 00:00:00 /bin/bash
root 14 0 1 12:48 pts/1 00:00:00 /bin/bash
root 29 14 0 12:48 pts/1 00:00:00 ps -ef
[root@8679da923e57 /]# exit
exit
PS >
PS > docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos centos7 5e35e350aded 4 weeks ago 203MB

dockerの起動(Ubuntu 18.04)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
PS > docker run -it -d --name ubuntu ubuntu:18.04
Unable to find image 'ubuntu:18.04' locally
18.04: Pulling from library/ubuntu
7ddbc47eeb70: Pull complete
c1bbdc448b72: Pull complete
8c3b70e39044: Pull complete
45d437916d57: Pull complete
Digest: sha256:6e9f67fa63b0323e9a1e587fd71c561ba48a034504fb804fd26fd8800039835d
Status: Downloaded newer image for ubuntu:18.04
9c20fc472edde1e26b19c08c2276c847fa61ed5958f9e1d7328247077fee3710
PS > docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9c20fc472edd ubuntu:18.04 "/bin/bash" 13 seconds ago Up 12 seconds ubuntu
8679da923e57 centos:centos7 "/bin/bash" 5 minutes ago Up 5 minutes centos7
PS > docker exec -it ubuntu /bin/bash
root@9c20fc472edd:/# ls -al
total 72
drwxr-xr-x 1 root root 4096 Dec 10 12:53 .
drwxr-xr-x 1 root root 4096 Dec 10 12:53 ..
-rwxr-xr-x 1 root root 0 Dec 10 12:53 .dockerenv
drwxr-xr-x 2 root root 4096 Oct 29 21:25 bin
drwxr-xr-x 2 root root 4096 Apr 24 2018 boot
drwxr-xr-x 5 root root 360 Dec 10 12:53 dev
drwxr-xr-x 1 root root 4096 Dec 10 12:53 etc
drwxr-xr-x 2 root root 4096 Apr 24 2018 home
drwxr-xr-x 8 root root 4096 May 23 2017 lib
drwxr-xr-x 2 root root 4096 Oct 29 21:25 lib64
drwxr-xr-x 2 root root 4096 Oct 29 21:25 media
drwxr-xr-x 2 root root 4096 Oct 29 21:25 mnt
drwxr-xr-x 2 root root 4096 Oct 29 21:25 opt
dr-xr-xr-x 144 root root 0 Dec 10 12:53 proc
drwx------ 2 root root 4096 Oct 29 21:25 root
drwxr-xr-x 1 root root 4096 Oct 31 22:20 run
drwxr-xr-x 1 root root 4096 Oct 31 22:20 sbin
drwxr-xr-x 2 root root 4096 Oct 29 21:25 srv
dr-xr-xr-x 13 root root 0 Dec 10 12:48 sys
drwxrwxrwt 2 root root 4096 Oct 29 21:25 tmp
drwxr-xr-x 1 root root 4096 Oct 29 21:25 usr
drwxr-xr-x 1 root root 4096 Oct 29 21:25 var
root@9c20fc472edd:/# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 12:53 pts/0 00:00:00 /bin/bash
root 11 0 0 12:54 pts/1 00:00:00 /bin/bash
root 22 11 0 12:55 pts/1 00:00:00 ps -ef
root@9c20fc472edd:/# exit
exit
PS > docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos centos7 5e35e350aded 4 weeks ago 203MB
ubuntu 18.04 775349758637 5 weeks ago 64.2MB

コメント・シェア



nullpo

めも


募集中


Japan