20200929のdockerに関する記事は12件です。

エンジニアの本棚卸し

目的

自分がインプットしてきた技術関連知識の足跡整理。
文字にするとキリがないので、面倒ではない視覚的に集約されているという点で本棚の書籍写真でペタペタ整理。

足跡

入り口はC言語

C言語、C++

猫でも分かるC言語で自分が猫未満であることを悟り、苦しんで〜みたいな名前の書籍を読んだ記憶。
DXLibraryを使用してゲーム製作をしたり、遺伝的アルゴリズムでレースゲームのゴール時間を最適化したり、TCP/IPレイヤをイジったり、二度デストラクタを呼び壊したり、ダングリングポインタを参照して壊したり、壊したり。

Webアプリケーションに興味が出てPHPあたり

PHP、JavaScript
Webアプリケーションを作りたくてPHP(時代を感じる)。
当時はLaravelではなくCakePHP,Symfonyとかの時代。Cakeを使ってWebアプリケーションを作っていたもののフレームワーク特有のブラックボックに薄気味悪さを覚えたため、一旦それは捨ててMVCフレームワークの自作に舵を切り替えた。
その後、数年してからREST APIでバックエンドとフロントエンドを接続するみたいなものが流行りだしたときにLaravelとReactでチーム開発した。

オブジェクトモデリングに興味が出てJava

Java
現実世界の写像(モデリング)ってなんぞ、と思いJava。
とやかく言われることの多い言語であるものの、複雑度の高いシステム構築においては安定している。

エンジニアとして知識領域を開拓する礎になった恋のキューピッド的な言語。

OSが知りたいです

OS
私達人間に何を隠しているのOSさん、ということでOS。
LINUXプログラミングインタフェースは学生のときに夏休みを使って読み切った(覚えてないけど)。

CPUが知りたいです

CPU
演算あたりの機構が知りたくてパタヘネ本とか、CPUの創りかたとか。
左のほうにある本はAPI設計やら、正規表現エンジンやら、Androidアプリとかに興味を持ったときの。

副作用のない言語?

関数型
保守性や疎結合などの文脈で関数型言語に興味を持った(ように記憶している)。
最初はCommonLisp。本屋でリスプエイリアンと目が合った。

今はRustが好き。
メモリ安全、ゼロコスト抽象化、GCのない軽量なランタイム。

機械学習やスクレイピング、デバッガ

P_20200929_205153.jpg
脳内シナプスによるネットワークを模倣ってなにを言ってるの、と興味を持ち自作系のお魚本から。
テンソルフローの計算グラフが作れないので基本Keras(に逃げた)。

その他、Pythonはスクレイピングやデバッガのカスタマイズなどでちょくちょく使う。

私はパケットになりたい

ネットワーク
ネットワークってなにそれどうやって制御してるの、知りたい。
MPLSなにそれ、剥がされたい。

攻撃は最大の防御

セキュリティ
避けがたいクラッキングという中二病。
もちろん隔離された自分だけの環境で。

コンピューティングリソースに対する抜本的な認識刷新

コンテナとか
このあたりのコンピューティングリソースの変化はコペルニクス的転回(言いたいだけ)をもたらしましたね。

マークアップとスタイル

HTML
あまり得意ではないものの、意思疎通を図るために必要なので最低限は知っておきたい。
右の砂川物理学は関係ない。

DBさん腹のウチを見せてごらん

DB
性能改善系のプロジェクトに配属されたついでにDB解体。

鳥になって鳥瞰したい

アーキテクチャ
システムの設計というものを真剣に考え始めたときに。

無限多味スルメ

レビュー
実践UML、コード・クラフト、コードコンプリートあたりは読むたびに味が変わる。

その他1

コンパイラGC
リファクタとか、GC、コンパイラなど。

その他2

テストGit
テスト手法やらGitの仕組みやら。

振り返った所感

まだ埋もれた書籍はクローゼットに大量にあるものの、とりあえず本棚にあるもので振り返ってみた。

結論:「頭でっかちになってはいけない」

物事の正しさというものは話し手5割・聞き手5割の双方の責任のもとに成立している。
書籍においても同様に書き手5割・読み手5割。

誰かが言っていたらから正しいとか、あの本に書いてあったから正しいのような
話し手や書き手10割の責とするような姿勢でいてはいけないな、と最近は特に強く感じるようになった。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Windows10】【開発環境構築】VSCodeでunresolved import 'django.xxx' python(unresolved-import)が発生

発生事象

vscodeでdjango関連のunresolved importが発生。
たとえば、unresolved import 'django.urls' python(unresolved-import)といった具合です。

気持ち悪かったので、解消した対応方法を。

開発環境

  • Windows版dockerで開発環境を構築。Pythonの仮想環境はpipenvを利用しています。
項目 バージョン
OS Window10 2004
Python 3.8.2
docker 2.3.0.5
Editor VSCode:1.49.2
  • 仮想環境の各種ソフトウェアバージョンは下記の通りです。
項目 バージョン
OS ubunts:20.04
python 3.8.2
Django 3.0.6
gunicorn 20.0.4
psycopg2 2.8.5
PostgeSQL 2.3
nginx 1.17.10

仮想環境の構築は

  • appフォルダ直下で pipenv install を実行しています。
  • djangoプロジェクトは pipenv shell からappフォルダ直下で startproject で作成ています。

対応

1.ワークスペース直下に.envファイルを作成

2..envファイルに下記を記載

.\.env
PYTHONPATH = app\.venv\Lib\site-packages

3.VSCodeのenvFileの設定を確認します。

3-1.VSCodeのメニューから File->Preferences->Settings で設定を開きます。

Settings.png

3-3.検索窓に「python.envFile」を入力します。
3-4.python.envFileの値が「${workspaceFolder}/.env」であるならそのままで問題なし。おそらくデフォルトでワークスペース直下がパスとなっていると思います。

envfile.png

3-5.VSCodeを立ち上げなおす。

おそらく、django関連のunresolved importが解消されているかと

あとがき

VSCodeからは見えていないので当たり前といば当たり前なのですが、、、

参考にさせていただいたサイト

https://blog.mrym.tv/2019/08/vscode-python-unresolved-import/

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Windows10】【開発環境構築】VSCodeでunresolved import 'django.xxx' python(unresolved-import)が発生時の対応

発生事象

vscodeでdjango関連のunresolved importが発生。
たとえば、unresolved import 'django.urls' python(unresolved-import)といった具合です。

気持ち悪かったので、解消した対応方法を。

開発環境

  • Windows版dockerで開発環境を構築。Pythonの仮想環境はpipenvを利用しています。
項目 バージョン
OS Window10 2004
Python 3.8.2
docker 2.3.0.5
Editor VSCode:1.49.2
  • 仮想環境の各種ソフトウェアバージョンは下記の通りです。
項目 バージョン
OS ubunts:20.04
python 3.8.2
Django 3.0.6
gunicorn 20.0.4
psycopg2 2.8.5
PostgeSQL 2.3
nginx 1.17.10

仮想環境の構築は

  • Workplaces配下にappフォルダを作成しています。
  • appフォルダ直下で pipenv install を実行しています。
  • djangoプロジェクトは pipenv shell からappフォルダ直下で startproject で作成ています。

対応

1.ワークスペース直下に.envファイルを作成

2..envファイルに下記を記載

.\.env
PYTHONPATH = app\.venv\Lib\site-packages

3.VSCodeのenvFileの設定を確認します。

3-1.VSCodeのメニューから File->Preferences->Settings で設定を開きます。

Settings.png

3-3.検索窓に「python.envFile」を入力します。
3-4.python.envFileの値が「${workspaceFolder}/.env」であるならそのままで問題なし。おそらくデフォルトでワークスペース直下がパスとなっていると思います。

envfile.png

3-5.VSCodeを立ち上げなおす。

おそらく、django関連のunresolved importが解消されているかと

あとがき

VSCodeからは見えていないので当たり前といば当たり前なのですが、、、

参考にさせていただいたサイト

https://blog.mrym.tv/2019/08/vscode-python-unresolved-import/

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

DockerのlogをAWS CloudWatchに紐付けしVSCodeでリアルタイムに監視する

はじめに

AWS EC2内のDockerコンテナ上で動くサービス(docker-composeで管理)のログをCloudWatchLogsに投げ、VSCodeでリアルタイム監視ができるまでの手順をまとめる。

  • Dockerのlog driverについて
  • CloudWatchLogsへの登録
  • VSCodeのAWS拡張についてとログの閲覧

Dockerのlog driverについて

Dockerの標準機能で/var/lib/docker/containers/にコンテナ内のログを出力するようになっている。そのため、Linuxのlogrotate等を使用する必要はない。
docker-composeでの実装例は以下の通り。

docker-compose.yml
version: "3"
services:
  hello:
    image: "busybox:latest"
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

CloudWatchLogsへの登録

上記で解説した、Dockerのlog driverを使用してログの出力先をCloudWatchLogsに変更することができる。
docker-composeでの実装例は以下の通り。

docker-compose.yml
version: '3'
services:
  app:
    build:
      context: .
      dockerfile: prod/Dockerfile
    restart: always
    expose:
      - 8000
    environment:
      - TZ=Asia/Tokyo
    logging:
      driver: awslogs
      options:
        awslogs-region: ap-northeast-1
        awslogs-group: log-group-name
        tag: "{{.ImageName}}.{{.Name}}.{{.FullID}}"
  nginx:
    build:
      context: .
      dockerfile: nginx/Dockerfile
    restart: always
    ports:
      - 8080:80
    depends_on:
      - app
    logging:
      driver: awslogs
      options:
        awslogs-region: ap-northeast-1
        awslogs-group: log-group-name
        tag: "{{.ImageName}}.{{.Name}}.{{.FullID}}"

docker-composeではサービスごとにlog driverの設定を記述する。
awslogs-groupにはマネジメントコンソールで作成したロググループ名を書く。

VSCodeのAWS拡張についてとログの閲覧

VSCodeの拡張機能の検索窓にawsと打ち込めば、下の画像のようなAWS Toolkitが表示されるので、それをインストールする。
スクリーンショット 2020-09-29 17.43.59.png
リージョンとアクセスキーを指示に従って設定する。
スクリーンショット 2020-09-29 17.47.32.png
上の画像のCloudWatch Logsのタブを開くとロググループが表示されるので、右クリックしview log streamを選択する。
Output Colorizer拡張をインストールしておくと、ログをハイライト付きで見ることができるので入れるとよい。

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

DockerのlogをAWS CloudWatchに紐付けしリアルタイムに監視する。

はじめに

AWS EC2内のDockerコンテナ上で動くサービス(docker-composeで管理)のログをCloudWatchLogsに投げ、VSCodeでリアルタイム監視ができるまでの手順をまとめる。

  • Dockerのlog driverについて
  • CloudWatchLogsへの登録
  • VSCodeのAWS拡張についてとログの閲覧

Dockerのlog driverについて

Dockerの標準機能で/var/lib/docker/containers/にコンテナ内のログを出力するようになっている。そのため、Linuxのlogrotate等を使用する必要はない。
docker-composeでの実装例は以下の通り。

docker-compose.yml
version: "3"
services:
  hello:
    image: "busybox:latest"
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

CloudWatchLogsへの登録

上記で解説した、Dockerのlog driverを使用してログの出力先をCloudWatchLogsに変更することができる。
docker-composeでの実装例は以下の通り。

docker-compose.yml
version: '3'
services:
  app:
    build:
      context: .
      dockerfile: prod/Dockerfile
    restart: always
    expose:
      - 8000
    environment:
      - TZ=Asia/Tokyo
    logging:
      driver: awslogs
      options:
        awslogs-region: ap-northeast-1
        awslogs-group: log-group-name
        tag: "{{.ImageName}}.{{.Name}}.{{.FullID}}"
  nginx:
    build:
      context: .
      dockerfile: nginx/Dockerfile
    restart: always
    ports:
      - 8080:80
    depends_on:
      - app
    logging:
      driver: awslogs
      options:
        awslogs-region: ap-northeast-1
        awslogs-group: log-group-name
        tag: "{{.ImageName}}.{{.Name}}.{{.FullID}}"

docker-composeではサービスごとにlog driverの設定を記述する。
awslogs-groupにはマネジメントコンソールで作成したロググループ名を書く。

VSCodeのAWS拡張についてとログの閲覧

VSCodeの拡張機能の検索窓にawsと打ち込めば、下の画像のようなAWS Toolkitが表示されるので、それをインストールする。
スクリーンショット 2020-09-29 17.43.59.png
リージョンとアクセスキーを指示に従って設定する。
スクリーンショット 2020-09-29 17.47.32.png
上の画像のCloudWatch Logsのタブを開くとロググループが表示されるので、右クリックしview log streamを選択する。
Output Colorizer拡張をインストールしておくと、ログをハイライト付きで見ることができるので入れるとよい。

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

DevContainer で Ruby 開発する際に厄介な BUNDLE_APP_CONFIG

TL;DR

  • Docker 公式の ruby イメージでセットされている環境変数 BUNDLE_APP_CONFIG は DevContainer 内での開発において邪魔になることがある
  • BUNDLE_APP_CONFIG の影響を無くしたい場合は devcontainer.json に以下を記述すると良い
.devcontainer/devcontainer.json
{
  // ...
  "remoteEnv": {
    "BUNDLE_APP_CONFIG": null
  },
  // ...
}

厄介な BUNDLE_APP_CONFIG

VSCode Remote - Containers での Ruby 開発では大抵の場合、Docker 公式の ruby イメージ をベースイメージにして DevContainer を作ることになる1かと思いますが、このイメージには厄介な問題があります。

それが環境変数 BUNDLE_APP_CONFIG です。
Dockerfile 内で ENV 命令によりデフォルトで /usr/local/bundle に設定されています。

BUNDLE_APP_CONFIG は bundler のアプリケーションローカルな設定 (bundle config set --local した際に作られる設定) をどこに保存するかを指定するための環境変数です。
この環境変数が設定されていない場合、bundler はアプリケーションルートの .bundle/ 以下に設定を作成します。

さて、話を移して VSCode の DevContainer で Ruby 開発をする場合、インストールした gem を永続化しつつコンテナにマウントするには以下のようにワークスペース内の vendor ディレクトリ等に突っ込んでおきたいところです。2

$ bundle config set --local path vendor/bundle

この設定により path 設定が記述された設定ファイルが通常は .bundle/config として保存されるはずです。ローカル設定にしたことでワークスペース内に設定ファイルが作られ、コンテナを破棄しても再設定は不要となります。
しかし、前述のように Docker 公式の ruby イメージでは BUNDLE_APP_CONFIG が設定されてしまっているため、このローカル設定は /usr/local/bundle/config に保存されてしまいます。

bundle config で確認してみると以下のような感じです。

$ bundle config
Settings are listed in order of priority. The top value will be used.
path
Set for your local app (/usr/local/bundle/config): "vendor/bundle"

app_config
Set via BUNDLE_APP_CONFIG: "/usr/local/bundle"

silence_root_warning
Set via BUNDLE_SILENCE_ROOT_WARNING: true

これでは Rebuild などによりコンテナを破棄した際に設定が失われてしまうため、都度 bundle config ... を実行するか、/usr/local/bundle をホストからマウントするようにするなどの工夫が必要になってしまいます。

スマートに解決するには BUNDLE_APP_CONFIG 自体を何とかした方が良いでしょう。

ちなみに公式イメージで BUNDLE_APP_CONFIG が設定されているのは上記の逆の考え方で、「ホスト側の .bundle/config がコンテナ内に影響を与えないようにするため」のようです3

2020/09/30 追記
コンテナ内でしか作業しない (= ホストと .bundle/vendor/ を共有する必要がない) のであれば BUNDLE_APP_CONFIG はそのままにして別途作成した volume を /usr/local/bundle にマウントした方が良さそうです。特に Docker for Mac では bind mount 時の Disk I/O が遅いため、ワークスペース内に gem を入れる設定だと bundle install 等に時間がかかってしまう可能性があります。

対策

× BUNDLE_APP_CONFIG に空文字を設定する

公式ドキュメント に記載されている方法です。

The environment variables we set are canonically listed in the above-linked Dockerfiles, but some of them include GEM_HOME, BUNDLE_PATH, BUNDLE_BIN, BUNDLE_SILENCE_ROOT_WARNING, and BUNDLE_APP_CONFIG.

If these cause issues for your use case (running multiple Ruby applications in a single container, for example), setting them to the empty string should be sufficient for undoing their behavior.

結論から言うとこの方法ではうまくいきません。
bundler は BUNDLE_APP_CONFIG の有無だけを見ている4ので、空文字が設定されている場合はカレントディレクトリ直下に config ファイルが作成されます。

実験してみましょう。
DevCotainer 用の Dockerfile で BUNDLE_APP_CONFIG に空文字をセットします。

devcontainer/Dockerfile
FROM ruby:2.7

# 空文字を設定
ENV BUNDLE_APP_CONFIG=

# 以下略

DevContaier をビルドして中に入ってみます。
ターミナル上ではなぜか BUNDLE_APP_CONFIG が消えて問題なく動作します (理由は不明ですが VSCode の実装の問題かもしれません)。

$ bundle config
Settings are listed in order of priority. The top value will be used.
silence_root_warning
Set via BUNDLE_SILENCE_ROOT_WARNING: true
$ bundle config set --local path vendor/bundle
$ bundle config
Settings are listed in order of priority. The top value will be used.
path
Set for your local app (/workspace/sample_app/.bundle/config): "vendor/bundle"

silence_root_warning
Set via BUNDLE_SILENCE_ROOT_WARNING: true

問題となるのはデバッグ時です。
デバッガ (rdebug-ide) を Gemfile で管理し、bundle install でインストールしているケースを想定します。
以下のような launch.json になるはずです。

.vscode/launch.json
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Debug Local File",
      "type": "Ruby",
      "request": "launch",
      "program": "${workspaceFolder}/main.rb",
      "useBundler": true
    }
  ]
}

デバッグを実行すると DEBUG CONSOLE に以下のように必要な gem が見つからない旨のエラーが出てしまいます。

bundler: failed to load command: rdebug-ide (/usr/local/bundle/bin/rdebug-ide)
Bundler::GemNotFound: Could not find concurrent-ruby-1.1.7 in any of the sources
  /usr/local/lib/ruby/2.7.0/bundler/spec_set.rb:86:in `block in materialize'
  /usr/local/lib/ruby/2.7.0/bundler/spec_set.rb:80:in `map!'
  /usr/local/lib/ruby/2.7.0/bundler/spec_set.rb:80:in `materialize'
  /usr/local/lib/ruby/2.7.0/bundler/definition.rb:170:in `specs'
  /usr/local/lib/ruby/2.7.0/bundler/definition.rb:237:in `specs_for'
  /usr/local/lib/ruby/2.7.0/bundler/definition.rb:226:in `requested_specs'
  /usr/local/lib/ruby/2.7.0/bundler/runtime.rb:101:in `block in definition_method'
  /usr/local/lib/ruby/2.7.0/bundler/runtime.rb:20:in `setup'
  /usr/local/lib/ruby/2.7.0/bundler.rb:149:in `setup'
  /usr/local/lib/ruby/2.7.0/bundler/setup.rb:20:in `block in <top (required)>'
  /usr/local/lib/ruby/2.7.0/bundler/ui/shell.rb:136:in `with_level'
  /usr/local/lib/ruby/2.7.0/bundler/ui/shell.rb:88:in `silence'
  /usr/local/lib/ruby/2.7.0/bundler/setup.rb:20:in `<top (required)>'

これは、デバッグ用のサブプロセスでは BUNDLE_APP_CONFIG="" が効いているために .bundle/config が参照されず path 設定が読み込まれないためです。

BUNDLE_APP_CONFIG.bundle のパスを設定してしまう (Dockerfile)

例えば以下のように Dockerfile などでローカル設定用の .bundle の絶対パスを指定してしまう方法です。

devcontainer/Dockerfile
ENV BUNDLE_APP_CONFIG=/workspace/.bundle

この方法であれば大体うまくいきますが、モノレポに複数のプロジェクトを突っ込んでいるケース (Gemfile が複数あるケース) には対応できません。

BUNDLE_APP_CONFIG.bundle のパスを設定してしまう (VSCode 設定)

例えば上記のデバッグがうまくいかない問題は以下のように解決できます。

.vscode/launch.json
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Debug Local File",
      "type": "Ruby",
      "request": "launch",
      "program": "${workspaceFolder}/main.rb",
      "useBundler": true,
      "env": {
        "BUNDLE_APP_CONFIG": "${workspaceFolder}/.bundle"
      }
    }
  ]
}

この方法であれば Multi-root Workspace にすることでモノレポのケースにも対応することができます。
ただしこの設定だけではデバッグ用のサブプロセスにしか有効にならないので、必要に応じて settings.json のターミナル設定や tasks.json にも同様の設定を記述する必要があります。
また、何らかの理由で BUNDLE_APP_CONFIG を設定して使っている人と launch.json 等の設定を共有することが難しくなります。

〇 devcontainer.json の設定で BUNDLE_APP_CONFIG を削除する

下記のような設定を devcontainer.json に追加することで、環境変数を空にするのでも上書きするのでもなく削除 (unset) することができます。

.devcontainer/devcontainer.json
{
  // ...
  "remoteEnv": {
    "BUNDLE_APP_CONFIG": null
  },
  // ...
}

この方法であればコンテナ内の VSCode プロセス及びそのサブプロセス全てで BUNDLE_APP_CONFIG が削除されます。
個人的にはこの方法が最も副作用が少なそうなのでおすすめです。


  1. mcr.microsoft.com/vscode/devcontainers/ruby もベースはこのイメージです 

  2. 余談ですが bundle install--path オプションは非推奨になったんですね…最近知りました 

  3. https://github.com/docker-library/ruby/issues/129 

  4. 2020年9月現在の最新 v2.4.1 ではこうなっています 

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

CentOS 7 で Docker Registry をローカルに立てる

はじめに

DockerHub にいろいろとイメージがあるものの、自分で作った Docker image を自分のRegistry において好きな時にダウンロードして起動したいと思ってきた。

Dockerfile を用意して DockerHub からダウンロードした Docker image から作成してもいいのだけど意外と時間がかかるので、準備完了状態のイメージを用意して、どっかの Docker のサーバーに置いておきたい。

HTTPS で証明書登録した通信もできるが、内部的な利用のためあくまで、さくっと利用できる環境を用意する方法です。

サーバとクライアントで2つの環境 (VMなど) を用意しておいてください。

手順

大まかに以下の手順

  • docker のインストール
  • docker の起動
  • Docker Registry の用意
  • サーバ側でイメージの用意(ダウンロードとRegistry)
  • Docker Registry からイメージのダウンロード
    • サーバ側でダウンロード
    • クライアント側でダウンロード

Docker のインストール

Redistry のサーバ、クライアント側にインストールする必要がある。
docker を rpm インストールするにはダウンロード先登録が必要。

yum -y install yum-utils
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum install -y docker-ce

Docker の起動

Redistry のサーバ、クライアント側で docker のサービスを起動し、OS起動時に自動起動させる。

systemctl start docker
systemctl enable docker

Docker Registry の用意

Registry のサーバで、Registry のイメージをダウンロードする

docker pull registry

以下のように docker image が追加される

docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
registry            latest              2d4f4b5309b1        3 months ago        26.2MB

Docker Registry の起動

Docker Registry を起動する。
このとき、Registry 上のイメージを永続化させたいのでホスト OS のディレクトリをコンテナにマウントさせる。

docker run -d -p 5000:5000 \
    -v /var/opt:/var/lib/registry \
    registry

コンテナが起動したことを確認

docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
35b3882b8536        registry            "/entrypoint.sh /etc…"   About an hour ago   Up About an hour    0.0.0.0:5000->5000/tcp   dreamy_roentgen

ホスト OS に以下のようなディレクトリができて、この下にマウントされる。

ls /var/opt/docker/registry/v2/
blobs  repositories

イメージを登録すると以下のように repositories 以下にイメージが保存されるディレクトリである。

ls -l /var/opt/docker/registry/v2/repositories/aaa
合計 0
drwxr-xr-x 5 root root 55  9月 16 15:33 centos_local

サーバ側でイメージの用意(ダウンロードとRegistry)

ローカルの Repository サーバに登録する元のイメージをダウンロード

なんでもいいが、とりあえず CentOS をダウンロード

docker pull centos
Using default tag: latest
latest: Pulling from library/centos
3c72a8ed6814: Pull complete
Digest: sha256:76d24f3ba3317fa945743bb3746fbaf3a0b752f10b10376960de01da70685fbd

ダウンロードできたことを確認

docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos              latest              0d120b6ccaa8        5 weeks ago         215MB
registry            latest              2d4f4b5309b1        2 months ago        26.2MB

docker Resistry へ登録するイメージを作成(タグ付け)

本来は Dockerfile などを利用して様々なツールや設定をしたイメージを作るのだが、今回は単純にダウンロードした CentOS のイメージをそのまま使う

docker tag centos localhost:5000/aaa/centos_local:1.0

タグ付けをすると以下のようにイメージができる

docker images
REPOSITORY                          TAG                 IMAGE ID            CREATED             SIZE
centos                              latest              0d120b6ccaa8        5 weeks ago         215MB
localhost:5000/aaa/centos_local   1.0                 0d120b6ccaa8        5 weeks ago         215MB
registry                            latest              2d4f4b5309b1        2 months ago        26.2MB

docker Resistry へイメージを登録

タグ付けしたイメージを docker Registry へ登録する

docker push localhost:5000/aaa/centos_local:1.0
The push refers to repository [localhost:5000/iseki/centos_local]
291f6e44771a: Pushed
1.0: digest: sha256:fc4a234b91cc4b542bac8a6ad23b2ddcee60ae68fc4dbd4a52efb5f1b0baad71 size: 529

登録後は、イメージは不要になるので削除

docker rmi localhost:5000/iseki/centos_local:1.0
Untagged: localhost:5000/iseki/centos_local:1.0
Untagged: localhost:5000/iseki/centos_local@sha256:fc4a234b91cc4b542bac8a6ad23b2ddcee60ae68fc4dbd4a52efb5f1b0baad71

削除後、一覧にイメージがないことを確認

docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos              latest              0d120b6ccaa8        5 weeks ago         215MB
registry            latest              2d4f4b5309b1        2 months ago        26.2MB

Docker Registry からイメージのダウンロード

サーバ側でダウンロード

サーバからからは以下のコマンドを実行してダウンロードできる

docker pull localhost:5000/aaa/centos_local:1.0

クライアント側でダウンロード

クライアント側からは、「クライアント側」に以下の設定を入れないと接続ができない

cat /etc/docker/daemon.json
{ "insecure-registries":["<Docker RegistoryのサーバーIP、またはホスト名>:5000"] }

上記の設定をして、docker のサービスを再起動

systemctl restart docker

この状態で、docker Registroy サーバからイメージを取得するコマンドを実行する。

docker pull 10.1.5.25:5000/aaa/centos_local:1.0
1.0: Pulling from iseki/centos_local
3c72a8ed6814: Pull complete
Digest: sha256:fc4a234b91cc4b542bac8a6ad23b2ddcee60ae68fc4dbd4a52efb5f1b0baad71
Status: Downloaded newer image for 10.1.5.25:5000/aaa/centos_local:1.0
10.1.5.25:5000/aaa/centos_local:1.0

docker のイメージがダウンロードされる

# docker images
REPOSITORY                          TAG                 IMAGE ID            CREATED             SIZE
10.1.5.25:5000/aaa/centos_local   1.0                 0d120b6ccaa8        7 weeks ago         215MB
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

docker-compose コンテナ内で通信ができない

解決したいこと

次のような構成でバックエンドと通信ができない。(Host is unreachable)

  • CentOS 8.2
  • docker-ce
  • docker-compose
   192.168.10.100
browser -- nginx[80] ------ backend container[80]
           (front)          (webmail)
           192.168.203.2    192.168.203.9

nginxからbackend containerに通信できない。(curlコマンドで試しても同様)
ただし、pingは通る。

解決方法

publicゾーン(default)に、マスカレードを有効にする。
※試行錯誤の結果なので、これが正しいかは未確認です...

sudo firewall-cmd --zone=public --add-masquerade --permanent
sudo firewall-cmd --reload
sudo systemctl restart docker

参考文献
https://forums.docker.com/t/docker-connection-refused-between-two-containers/68040/12

発生している問題・エラー

[user@centos8 mailu]$ sudo docker-compose exec front sh
/ # curl -LsS http://192.168.203.9
curl: (7) Failed to connect to 192.168.203.9 port 80: Host is unreachable
/ # ping 192.168.203.9
PING 192.168.203.6 (192.168.203.9): 56 data bytes
64 bytes from 192.168.203.9: seq=0 ttl=64 time=0.103 ms
64 bytes from 192.168.203.9: seq=1 ttl=64 time=0.094 ms
^C
--- 192.168.203.9 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.094/0.098/0.103 ms

該当するソースコード

https://setup.mailu.io/1.7/ から自動生成したものに対象変更を加えたもの。

mailu.env
# Mailu main configuration file
#
# This file is autogenerated by the configuration management wizard for compose flavor.
# For a detailed list of configuration variables, see the documentation at
# https://mailu.io

###################################
# Common configuration variables
###################################

# Set to a randomly generated 16 bytes string
SECRET_KEY=SECRETAAAAAAAAAA

# Subnet of the docker network. This should not conflict with any networks to which your system is connected. (Internal and external!)
SUBNET=192.168.203.0/24

# Main mail domain
DOMAIN=example.org

# Hostnames for this server, separated with comas
HOSTNAMES=example.org

# Postmaster local part (will append the main mail domain)
POSTMASTER=admin

# Choose how secure connections will behave (value: letsencrypt, cert, notls, mail, mail-letsencrypt)
TLS_FLAVOR=notls

# Authentication rate limit (per source IP address)
AUTH_RATELIMIT=10/minute;1000/hour

# Opt-out of statistics, replace with "True" to opt out
DISABLE_STATISTICS=False

###################################
# Optional features
###################################

# Expose the admin interface (value: true, false)
ADMIN=true

# Choose which webmail to run if any (values: roundcube, rainloop, none)
WEBMAIL=rainloop

# Dav server implementation (value: radicale, none)
WEBDAV=none

# Antivirus solution (value: clamav, none)
ANTIVIRUS=none

###################################
# Mail settings
###################################

# Message size limit in bytes
# Default: accept messages up to 50MB
# Max attachment size will be 33% smaller
MESSAGE_SIZE_LIMIT=50000000

# Networks granted relay permissions
# Use this with care, all hosts in this networks will be able to send mail without authentication!
RELAYNETS=192.168.10.0/24

# Will relay all outgoing mails if configured
RELAYHOST=

# Fetchmail delay
FETCHMAIL_DELAY=600

# Recipient delimiter, character used to delimiter localpart from custom address part
RECIPIENT_DELIMITER=+

# DMARC rua and ruf email
DMARC_RUA=admin
DMARC_RUF=admin

# Welcome email, enable and set a topic and body if you wish to send welcome
# emails to all users.
WELCOME=false
WELCOME_SUBJECT=Welcome to your new email account
WELCOME_BODY=Welcome to your new email account, if you can read this, then it is configured properly!

# Maildir Compression
# choose compression-method, default: none (value: bz2, gz)
COMPRESSION=
# change compression-level, default: 6 (value: 1-9)
COMPRESSION_LEVEL=

###################################
# Web settings
###################################

# Path to redirect / to
WEBROOT_REDIRECT=/webmail

# Path to the admin interface if enabled
WEB_ADMIN=/webmin

# Path to the webmail if enabled
WEB_WEBMAIL=/webmail

# Website name
SITENAME=Mailu

# Linked Website URL
WEBSITE=https://mailu.io



###################################
# Advanced settings
###################################

# Log driver for front service. Possible values:
# json-file (default)
# journald (On systemd platforms, useful for Fail2Ban integration)
# syslog (Non systemd platforms, Fail2Ban integration. Disables `docker-compose log` for front!)
# LOG_DRIVER=json-file

# Docker-compose project name, this will prepended to containers names.
COMPOSE_PROJECT_NAME=mailu

# Default password scheme used for newly created accounts and changed passwords
# (value: BLF-CRYPT, SHA512-CRYPT, SHA256-CRYPT, MD5-CRYPT, CRYPT)
PASSWORD_SCHEME=BLF-CRYPT

# Header to take the real ip from
REAL_IP_HEADER=

# IPs for nginx set_real_ip_from (CIDR list separated by commas)
REAL_IP_FROM=

# choose wether mailu bounces (no) or rejects (yes) mail when recipient is unknown (value: yes, no)
REJECT_UNLISTED_RECIPIENT=

# Log level threshold in start.py (value: CRITICAL, ERROR, WARNING, INFO, DEBUG, NOTSET)
LOG_LEVEL=WARNING

###################################
# Database settings
###################################
DB_FLAVOR=sqlite
docker-compose.yml
# This file is auto-generated by the Mailu configuration wizard.
# Please read the documentation before attempting any change.
# Generated for compose flavor

version: '3'

services:

  # External dependencies
  redis:
    image: redis:alpine
    restart: always
    volumes:
      - "/usr/local/docker/mailu/redis:/data"

  # Core services
  front:
    image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}nginx:${MAILU_VERSION:-1.7}
    restart: always
    env_file: mailu.env
    logging:
      driver: json-file
    ports:
      - "192.168.10.100:80:80"
      - "::1:80:80"
      - "192.168.10.100:443:443"
      - "::1:443:443"
      - "192.168.10.100:25:25"
      - "::1:25:25"
      - "192.168.10.100:465:465"
      - "::1:465:465"
      - "192.168.10.100:587:587"
      - "::1:587:587"
      - "192.168.10.100:110:110"
      - "::1:110:110"
      - "192.168.10.100:995:995"
      - "::1:995:995"
      - "192.168.10.100:143:143"
      - "::1:143:143"
      - "192.168.10.100:993:993"
      - "::1:993:993"
    volumes:
      - "/usr/local/docker/mailu/certs:/certs"
      - "/usr/local/docker/mailu/overrides/nginx:/overrides"

  admin:
    image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}admin:${MAILU_VERSION:-1.7}
    restart: always
    env_file: mailu.env
    ports:
      - 192.168.10.100:8080:80
      - 80
    volumes:
      - "/usr/local/docker/mailu/data:/data"
      - "/usr/local/docker/mailu/dkim:/dkim"
    depends_on:
      - redis

  imap:
    image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}dovecot:${MAILU_VERSION:-1.7}
    restart: always
    env_file: mailu.env
    volumes:
      - "/usr/local/docker/mailu/mail:/mail"
      - "/usr/local/docker/mailu/overrides:/overrides"
    depends_on:
      - front

  smtp:
    image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}postfix:${MAILU_VERSION:-1.7}
    restart: always
    env_file: mailu.env
    volumes:
      - "/usr/local/docker/mailu/overrides:/overrides"
    depends_on:
      - front

  antispam:
    image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}rspamd:${MAILU_VERSION:-1.7}
    restart: always
    env_file: mailu.env
    volumes:
      - "/usr/local/docker/mailu/filter:/var/lib/rspamd"
      - "/usr/local/docker/mailu/dkim:/dkim"
      - "/usr/local/docker/mailu/overrides/rspamd:/etc/rspamd/override.d"
    depends_on:
      - front

  # Optional services

  webdav:
    image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}radicale:${MAILU_VERSION:-1.7}
    restart: always
    env_file: mailu.env
    volumes:
      - "/usr/local/docker/mailu/dav:/data"


  # Webmail
  webmail:
    image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}rainloop:${MAILU_VERSION:-1.7}
    restart: always
    env_file: mailu.env
    volumes:
      - "/usr/local/docker/mailu/webmail:/data"
    depends_on:
      - imap


networks:
  default:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 192.168.203.0/24
    # 以下はお試し
    driver_opts:
      com.docker.network.bridge.enable_icc: "true"
      com.docker.network.bridge.enable_ip_masquerade: "true"

自分で試したこと

  • enable_iccが有効になっていないため、コンテナ間で通信ができない?

    • 前述の設定の通り設定したが、結果は同じだった(通信できない)
    • Enable or Disable Inter Container Connectivity docker bridge-driver-options
  • docker0ネットワークをtrustedゾーンへ移動

    • 結果は同じだった(通信できない)
  • CentOS8で、docker-ceでは通信できない?!

    • stackoverflow
    • CentOS7では同じソースで正しく動作するとのこと

環境

env
[user@centos8 mailu]$ cat /etc/centos-release
CentOS Linux release 8.2.2004 (Core)
[user@centos8 mailu]$ sudo docker system info
Client:
 Debug Mode: false

Server:
 Containers: 8
  Running: 8
  Paused: 0
  Stopped: 0
 Images: 10
 Server Version: 19.03.13
 Storage Driver: overlay2
  Backing Filesystem: xfs
  Supports d_type: true
  Native Overlay Diff: true
 Logging Driver: json-file
 Cgroup Driver: cgroupfs
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
 Swarm: inactive
 Runtimes: runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: 8fba4e9a7d01810a393d5d25a3621dc101981175
 runc version: dc9208a3303feef5b3839f4323d9beb36df0a9dd
 init version: fec3683
 Security Options:
  seccomp
   Profile: default
 Kernel Version: 4.18.0-193.19.1.el8_2.x86_64
 Operating System: CentOS Linux 8 (Core)
 OSType: linux
 Architecture: x86_64
 CPUs: 2
 Total Memory: 1.784GiB
 Name: centos8
 ID: EENH:WZZJ:FROE:QNUP:QGVT:RRIN:RUR3:THIT:F22Q:IMVS:4GEL:DYIC
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 Registry: https://index.docker.io/v1/
 Labels:
 Experimental: false
 Insecure Registries:
  127.0.0.0/8
 Live Restore Enabled: false
[user@centos8 mailu]$ sudo docker-compose --version
docker-compose version 1.27.4, build 40524192
docker-inspect
[user@centos8 ~]$ sudo docker inspect  mailu_default
[
    {
        "Name": "mailu_default",
        "Id": "27df81922313814a564c7a551a0c8cf3ea21603dba58002e73ba8f944e565c20",
        "Created": "2020-09-27T21:02:05.901818833-04:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "192.168.203.0/24"
                }
            ]
        },
        "Internal": false,
        "Attachable": true,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "1facc50c2feb49fca0033ed6642a6610c9bf79e616627fc957eacbb0638a5545": {
                "Name": "mailu_antispam_1",
                "EndpointID": "db33492d3378ecee9c057343493e6f1666f5166db94ed0c29830fb6821bc0cf3",
                "MacAddress": "02:42:c0:a8:cb:06",
                "IPv4Address": "192.168.203.6/24",
                "IPv6Address": ""
            },
            "3a4cd121bc28240d46699040f407afdd0702b7c31e8272f7da7a80c743ba7357": {
                "Name": "mailu_front_1",
                "EndpointID": "2588705b19c4d8b79c429d2cda66881fa93545a704f7763c912a764676185893",
                "MacAddress": "02:42:c0:a8:cb:02",
                "IPv4Address": "192.168.203.2/24",
                "IPv6Address": ""
            },
            "51c2da8ef177eb6a33d3e67af20aba5d791703a2d705e307ab9a458a7c4c4209": {
                "Name": "mailu_webmail_1",
                "EndpointID": "eb3d2b060aed84eb814d9d52dbe808a7073a52bb87d7dc7f335cbfe23bc03c28",
                "MacAddress": "02:42:c0:a8:cb:09",
                "IPv4Address": "192.168.203.9/24",
                "IPv6Address": ""
            },
            "80f0b528ea72121e8281a7734264989d2740bf5c89b7df866dc219b6016d52f5": {
                "Name": "mailu_admin_1",
                "EndpointID": "6770a86d9d3678ca98af052b9fc3e8fb2daf046166f8dbf819af5b7e7d49a1a5",
                "MacAddress": "02:42:c0:a8:cb:05",
                "IPv4Address": "192.168.203.5/24",
                "IPv6Address": ""
            },
            "95f81670bd10572ccaf6f778228bab6a808b5bcc74061a09c44090359b89b58e": {
                "Name": "mailu_redis_1",
                "EndpointID": "593ddd4e0ff2082ee9243b9eff0b4cc8301ace0438e84c0af02cc9f775a07eae",
                "MacAddress": "02:42:c0:a8:cb:04",
                "IPv4Address": "192.168.203.4/24",
                "IPv6Address": ""
            },
            "bbeb23a885a4e41ac47a25bc1c296b817f6eeff9baf2d23b26f4ac9513f04cae": {
                "Name": "mailu_smtp_1",
                "EndpointID": "b4e3b3c2e3676069039660ff5aab6529ed224a343d3eca60262cfea3341b6b4a",
                "MacAddress": "02:42:c0:a8:cb:08",
                "IPv4Address": "192.168.203.8/24",
                "IPv6Address": ""
            },
            "bc78cf9b396530c65ff202acb9e925f236e9e655a7e35cf1159d502b653f2d05": {
                "Name": "mailu_imap_1",
                "EndpointID": "c92a0e46b68bb2f594dfb7395a6e6d206d0497c2b30103395edcafa547153c10",
                "MacAddress": "02:42:c0:a8:cb:07",
                "IPv4Address": "192.168.203.7/24",
                "IPv6Address": ""
            },
            "f25bec8296de7375d78c190b8fbe8dc2ed1eff3d3adbe53655428341f53b3da1": {
                "Name": "mailu_webdav_1",
                "EndpointID": "0154fd24c909d460830539cfe55fbb8b9c201abc17b1d2ae5cbbd49964e59e1a",
                "MacAddress": "02:42:c0:a8:cb:03",
                "IPv4Address": "192.168.203.3/24",
                "IPv6Address": ""
            }
        },
        "Options": {
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true"
        },
        "Labels": {
            "com.docker.compose.network": "default",
            "com.docker.compose.project": "mailu",
            "com.docker.compose.version": "1.27.4"
        }
    }
]
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

KubernetesとDockerを使用してPython APIを開発およびデプロイする

image.png

はじめに

Dockerは最も人気のあるコンテナー化テクノロジーの1つです。使いやすく、開発者にとって使いやすいツールであり、スムーズかつ簡単に使用できることもあり、他の同様のテクノロジーよりも人気があります。 2013年3月の最初のオープンソースリリース以来、Dockerは開発者や運用エンジニアから注目を集め、Docker Inc.によると、Dockerユーザーは1,050億を超えるコンテナーをダウンロードし、Docker Hubに580万のコンテナーをドッキングしました。プロジェクトのGithubには32,000以上のスターがあります。

現在、Dockerはそれほど主流になりました。 10万を超えるサードパーティプロジェクトがこのテクノロジ-
を使用しており、コンテナ化のスキルを持つ開発者の需要が高まっているのも事実です。

この記事は、最初にDockerを使用してアプリケーションをコンテナ化する方法を説明し、次にDocker Composeを使用して開発環境で実行する方法を解説していきます。メインアプリとしてPython APIを使用します。

MetricFireでは、Docker、Kubernetes、Pythonのセットアップの監視について、お助けできます。どのように役立つかをご確認いただくには、是非デモをご予約ください。

開発環境のセットアップ

開始する前に、いくつかの要件をインストールしていきます。 ここではFlaskで開発されたMini Python APIを使用します。 FlaskはPythonフレームワークであり、APIを迅速にプロトタイプ化するための優れた選択肢であり、私たちのアプリケーションはFlaskを使用して開発されます。 Pythonに慣れていない場合は、このAPIを作成する手順を以下に示します。

まず、Python仮想環境を作成して、依存関係を残りのシステム依存関係から分離します。 その前に、人気のあるPythonパッケージマネージャーであるPIPが必要です。

インストールは非常に簡単です。次の2つのコマンドを実行してみてください。

curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
python get-pip.py

参考までに、Python 3がインストールされている必要があります。 これを確認するには、次のように入力してください。

​python --version​

PIPをインストールした後、次のコマンドを使用して仮想環境をインストールします。

​pip install virtualenv​

公式ガイドに従って他のインストール方法を見つけることができます。 次に、仮想環境を作成するフォルダーのプロジェクトを作成し、アクティブ化します。 また、アプリのフォルダーとapp.pyというファイルを作成します。

mkdir app
cd app
python3 -m venv venv
. venv/bin/activate
mkdir code
cd code
touch app.py

特定の都市の天気を表示する簡単なAPIを作成します。 たとえば、ロンドンの天気を表示したいとします。 ルートを使用してリクエストする必要があります:

/london/uk

PIPを使用して「flask」および「requests」と呼ばれるPython依存関係をインストールする必要があります。 後でそれらを使用します:

pip install flask requests​

依存関係をrequirements.txtというファイルで「Freeze」することを忘れないでください。 このファイルは、後でアプリの依存関係をコンテナーにインストールするために使用されます。

pip freeze &gt; requirements.txt​

要件ファイルは次のようになります。

certifi==2019.9.11
chardet==3.0.4
Click==7.0
Flask==1.1.1
idna==2.8
itsdangerous==1.1.0
Jinja2==2.10.3
MarkupSafe==1.1.1
requests==2.22.0
urllib3==1.25.7
Werkzeug==0.16.0

APIのイニシャルコードは

from flask import Flask
app = Flask(__name__)

@app.route('/')
def index():
    return 'App Works!'

if __name__ == '__main__':
    app.run(host="0.0.0.0", port=5000)

テストするには、python app.pyを実行し、http://127.0.0.1:5000 /にアクセスする必要があります。 「AppWorks!」が表示されます。 Webページで。 openweathermap.orgのデータを使用するので、必ず同じWebサイトでアカウントを作成し、APIキーを生成してください。

次に、APIに特定の都市の気象データを表示させるための便利なコードを追加する必要があります。

@app.route('/&lt;string:city&gt;/&lt;string:country&gt;/')
def weather_by_city(country, city):
    url = 'https://samples.openweathermap.org/data/2.5/weather'
    params = dict(
        q=city + "," + country,
        appid= API_KEY,
    )
    response = requests.get(url=url, params=params)
    data = response.json()
    return data

そして、全体のコードは以下のようになります。

from flask import Flask
import requests

app = Flask(__name__)

API_KEY = "b6907d289e10d714a6e88b30761fae22"

@app.route('/')
def index():
    return 'App Works!'

@app.route('/&lt;string:city&gt;/&lt;string:country&gt;/')
def weather_by_city(country, city):

    url = 'https://samples.openweathermap.org/data/2.5/weather'
    params = dict(
        q=city + "," + country,
        appid= API_KEY,
    )

    response = requests.get(url=url, params=params)
    data = response.json()
    return data

if __name__ == '__main__':
    app.run(host="0.0.0.0", port=5000)

127.0.0.1:5000/london/ukにアクセスすると、次のようなJSONが表示されるはずです。

{
  "base": "stations",
  "clouds": {
    "all": 90
  },
  "cod": 200,
  "coord": {
    "lat": 51.51,
    "lon": -0.13
  },
...

Mini APIが機能しています。 Dockerを使用してコンテナ化しましょう。

Dockerを使用してアプリのコンテナーを作成する

APIのコンテナを作成しましょう。 最初のステップは、Dockerfileを作成することです。 Dockerfileは、イメージを構築するためにDockerデーモンが従う必要のあるさまざまな手順と指示を含む説明的なテキストファイルです。 イメージをビルドしたら、コンテナーを実行できるようになります。

Dockerfileは常にFROM命令で始まります。

FROM python:3
ENV PYTHONUNBUFFERED 1
RUN mkdir /app
WORKDIR /app
COPY requirements.txt /app
RUN pip install --upgrade pip
RUN pip install -r requirements.txt
COPY . /app
EXPOSE 5000
CMD [ "python", "app.py" ]

上記のファイルでは、次のことを行いました。

  1. 「python:3」というベースイメージを使用
  2. PYTHONUNBUFFEREDを1に設定。PYTHONUNBUFFEREDを1に設定すると、ログメッセージをバッファリングせずにストリームにダンプできます。
  3. フォルダー/ appを作成し、それをworkdirとして設定。
  4. 要件をコピーし、それを使用してすべての依存関係をインストール。
  5. アプリケーションを構成するすべてのファイル、つまりapp.pyファイルをworkdirにコピー。
  6. アプリがこのポートを使用するため、最終的にポート5000を公開し、app.pyを引数としてpythonコマンドを起動。 これにより、コンテナの起動時にAPIが起動。

Dockerfileを作成したら、イメージ名と選択したタグを使用してDockerfileをビルドする必要があります。 この例では、名前として「weather」を使用し、タグとして「v1」を使用します。

docker build -t weather:v1 .

Dockerfileとapp.pyファイルを含むフォルダー内からビルドしていることを確認してください。

コンテナをビルドした後、次を使用して実行できます。

docker run -dit --rm -p 5000:5000 --name weather weather:v1

-dオプションを使用するため、コンテナーはバックグラウンドで実行されます。 コンテナは「weather」(-name weather)と呼ばれます。 また、ホストポート5000を公開されたコンテナーポート5000にマップしたため、ポート5000でも到達可能です。

コンテナの作成を確認したい場合は、次を使用できます。

docker ps

次の出力と非常によく似た出力が表示されるはずです。

CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS              PORTS                    NAMES
0e659e41d475        weather:v1          "python app.py"     About a minute ago   Up About a minute   0.0.0.0:5000-&gt;5000/tcp   weather

これでAPIをクエリできるはずです。 CURLを使用してテストしてみましょう。

curl http://0.0.0.0:5000/london/uk/

最後のコマンドがJSONを返す必要がある場合:

{
  "base": "stations",
  "clouds": {
    "all": 90
  },
  "cod": 200,
  "coord": {
    "lat": 51.51,
    "lon": -0.13
...
}

開発のためのDocker Composeの使用

Docker Composeは、マルチコンテナーDockerアプリケーションを定義および実行するためにDockerInc。によって開発されたオープンソースツールです。 Docker Composeは、開発環境で使用することを目的としたツールでもあります。これにより、コンテナーを手動で再起動したり、変更のたびにイメージを再構築したりすることなく、コードの更新時にコンテナーを自動再ロードできます。 Composeがないと、Dockerコンテナのみを使用して開発するのにイライラは避けられないでしょう。

実装部分では、「docker-compose.yaml」ファイルを使用します。

これは、APIで使用している「docker-compose.yaml」ファイルです。

version: '3.6'
services:
  weather:
    image: weather:v1
    ports:
      - "5000:5000"
    volumes:
      - .:/app

上記のファイルで、イメージ「weather:v1」を使用するようにサービス「weather」を構成したことがわかります。 ホストポート5000をコンテナポート5000にマップし、現在のフォルダをコンテナ内の「/ app」フォルダにマウントします。

イメージの代わりにDockerfileを使用することもできます。 すでにDockerfileがあるので、この場合はこれをお勧めします。

version: '3.6'
services:
  weather:
    build: .
    ports:
      - "5000:5000"
    volumes:
      - .:/app

次に、「docker-compose up」を実行してサービスの実行を開始するか、「docker-compose up --build」を実行してビルドしてから実行します。

まとめ

この投稿では、Mini Python API用のDockerコンテナーを作成する方法を確認し、DockerComposeを使用して開発環境を作成しました。 GoやRailsなどの別のプログラミング言語を使用している場合は、いくつかの小さな違いを除いて、通常は同じ手順に従います。 MetricFire無料デモを予約して、MetricFireがモニタリング環境に適合するかどうかをご相談ください。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

node+dockerでbcryptしたら、エラーおきた

dockerとnodeの環境でbcryptライブラリを使ったときのエラー

dockerでnodeでbcryptを使うとエラーが起きます。
node_modulesをコピーしてしまうとエラーが起きるので、.dockerignoreを使いましょう

dockerignoreを使いましょう

tree
.
├── Dockerfile
├── app.js
├── node_modules
├── package-lock.json
├── package.json
└── .dockerignore ←これを追加
.dockerignore
node_moduels/

ちなみにDockerfileはこんな感じ

FROM node:12
WORKDIR /usr/src/app

COPY package.json ./
COPY package-lock.json ./
RUN npm install

COPY . .

CMD [ "npm", "start" ]
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Dockerを使ってPrivoxy+Torの環境を一瞬で作る

はじめに

Dockerを使うとPrivoxy + Torの環境を簡単に立ち上げられます。基本的に下記の公式ページを読めばわかる内容ですが、Dockerの便利さを実感できたので記事にします。

dperson/torproxy

なお今回はdperson/torproxyのイメージを利用していますが、Privoxy + Torのイメージは検索するといくつか見つかります。他は試していませんが、今回紹介するような簡単な要件ならばどれを使っても同じように可能だろうと思います。

Privoxy + Torをなぜ使うか

LinuxではTorを導入して起動するだけで、デフォルト設定だとローカルホストの9050番ポートにSOCKS5プロキシが立ち上がり、そのプロキシを使うことでTor経由のWebアクセスが可能となります。

しかし、curlなどによるアクセスなら良いのですが、場合によってはHTTPプロキシは使える一方でSOCKSプロキシを直接使えないことがあります。

その場合はPrivoxyとTorを組合わせて利用することになります。適切な設定をすると、PrivoxyによるHTTPプロキシ(デフォルトでは8118番ポート)を経由することでPrivoxy→Tor→Webサイトのような流れのアクセスが可能になります。

具体的な設定方法はたとえば次のようなページで紹介されています。

4.10. How do I use Privoxy together with Tor?

これはこれで問題はないのですが、Privoxyをインストールして設定ファイルを書き換えるなどするのはそれなりに面倒です。

Privoxyがローカルに残ってしまうのも少し気持ち悪いです。

Dockerで環境を立ち上げればそれらの問題を解決できます。

dockerコマンド

起動

次のようなコマンドでPrivoxy + Torのコンテナを起動します。

docker run -it -p 8118:8118 -p 9050:9050 -d dperson/torproxy

-p 8118:8118はポートのバインドを指定しています。

-p ホスト側ポート:コンテナ側ポートのような記法です。

したがってすでにホストの8118番ポートが使用されている場合は

docker run -it -p 8119:8118 -p 9050:9050 -d dperson/torproxy

のようにポート番号を使われていないものに変更すれば大丈夫です。
また、-p 9050:9050はTorのSOCKSプロキシに接続するためのポートなので、もしHTTPプロキシのみが必要な場合は、

docker run -it -p 8118:8118 -d dperson/torproxy

のように9050番ポートの設定を省略すればHTTPプロキシのみホストからアクセスできる状態で起動します。

動作確認

curlで動作確認を行います。

curl -L ipinfo.io

このようにipinfo.ioにcurlでアクセスすると接続元のIPなどが表示されます。プロキシを何も設定しないと当然自宅のIPアドレスが表示されるはずです。

コンテナをdocker run -it -p 8118:8118 -p 9050:9050 -d dperson/torproxyのコマンドで起動し、8118番ポートでPrivoxyのHTTPプロキシにアクセスできる場合は次のようなコマンドでプロキシ経由のWebアクセスを行います。

curl -Lx localhost:8118 ipinfo.io

(-xオプションでプロキシを指定します)

コンテナが起動し、正しくプロキシ経由のアクセスできている場合は自宅のものとは違うIPアドレスが表示されるはずです。

同様にSOCKSプロキシも確認します。

curl -Lx socks5h://localhost:9050 ipinfo.io

このコマンドでTor経由のアクセスになっていることを確認できるはずです。

終了する

次のコマンドで立ち上がっているコンテナを確認します。

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                 PORTS                                                      NAMES
ae9565085d51        dperson/torproxy    "/sbin/tini -- /usr/…"   8 hours ago         Up 8 hours (healthy)   0.0.0.0:8118->8118/tcp, 9050/tcp, 0.0.0.0:9050->9050/tcp   inspiring_brahmagupta

ここでCONTAINER IDもしくはNAMESを確認し、次のコマンドの引数にします。

docker stop ae9565085d51

docker stopの引数にCONTAINER IDもしくはNAMESを指定します。
これでコンテナが停止します。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

DockerをWindows 10 Homeで試してみる

概要

Windows HomeでもDocker Desktop for Windowsを使えるようになったらしいので試してみる。

Docker Desktop for Windowsをダウンロード

https://hub.docker.com/editions/community/docker-ce-desktop-windows/

Windowsのアップデート

そのままではインストール時にWindowsのバージョンが足らないと怒られるので
Windows Insider Programに登録してリリースプレビューチャネルを選択してWindowsをアップデートする。
screenshot_20200929_001242.png

アップデート後のバージョン
screenshot_20200929_001000.png

バージョンアップ後Docker Desktop for Windowsをインストールする。

試してみる

適当にCentOSをPullして起動してみる。

> docker pull centos
> docker run -i -t centos /bin/bash

2020-09-29 (4).png

無事起動することができた。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む