20211129のdockerに関する記事は9件です。

1つのKubernetesクラスタで複数のシングルテナント向けの証明書を取り扱う

背景 あるところに、Azure Kubernetes Serviceを用いたWebサービス公開に携わる一人のエンジニアがおりました。 ある日彼はこんなことを考えました。 (-"-)「今開発中の機能はサーバー負荷がかなり大きい…」 (-"-)「利用が集中すると他のユーザーに影響する恐れがある…」 (-"-)「でもユーザーによってはそういった形での業務影響が許されない…」 (・_・)!「よし、シングルテナント構成を取れるようにしよう」 そこで彼はハイパフォーマンスを要求するユーザー向けに個別のクラスタ構成を定義し、それぞれを別のnamespaceで動かすことを考えました。また各ユーザー向けには専用のサブドメインを切り、Azure DNSを用いてドメイン毎に別のクラスタが利用されるよう振り分けを行うことにしました。 めちゃ雑に図にするとこんな感じです。 本題 さて、もはや常時HTTPSが当たり前の時代で、彼のWebサービスでもHTTPS越しにサービスを公開しています。ドメインが増えればその当然そのサーバー証明書が必要になります。 証明書はお金で買うことも出来ますし、買った証明書はKubernetesのsecretを経由することで比較的に各Podへの配布ができます。しかし彼はケチでものぐさなエンジニアだったので、証明書を買うのにお金をかけることはしたくなかったし、証明書の期限が切れるたびにsecretを更新する手間をかけたくもなかったのです。 無料の証明書と言えばそう、Let's Encryptの出番です。幸い世の中にはLet's Encryptからの証明書取得を行うためのKubernetesアドオンがありましたし、親切にもAzureにはこれを利用するための公式ドキュメントがありました。 jetstack/cert-manager Azure Kubernetes Service (AKS) で HTTPS イングレス コントローラーを作成する 壁その1: Let's Encryptのレート制限 Let's Encryptに関して彼は全くの素人でしたが、ネット上のサンプルを参考に証明書の取得をすることは簡単にできました。 issuer.yml apiVersion: cert-manager.io/v1 kind: Issuer metadata: name: letsencrypt spec: acme: server: https://acme-v02.api.letsencrypt.org/directory email: hoge@example.com privateKeySecretRef: name: letsencrypt-key http01: {} certificate.yml apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: example-certificate spec: secretName: certs-example issuerRef: kind: Issuer name: letsencrypt commonName: "a.example.com" dnsNames: - "a.example.com" たったこれだけで a.example.com 向けの証明書が取得できたので、意気揚々と各名前空間上に同様のオブジェクトをデプロイしました。これはとても上手く行きました。 しかし価値を確信した刹那、とある記事が彼の目に留まりました。 レート制限 -Let's Encrypt- その記事にはこうあります。 主なレート制限としては、登録ドメインごとの証明書数 (1週間に50個まで) があります。登録ドメインとは、一般に言うと、あなたがドメイン名レジストラから購入したドメインの一部のことです。たとえば、www.example.com の場合、登録ドメインは example.com です。new.blog.example.co.uk の場合、登録ドメインは example.co.uk になります。 これは今後ユーザーが増え続けたとき、名前空間の数だけ証明書のリクエストが発生することでレート制限に引っ掛かる可能性を意味していました。 彼は詰みました。 解決策 ユーザー数が増えるにつれて大量のドメインが要るとは言っても、所詮は example.com のサブドメインが増えるに過ぎません。 ならば、ワイルドカード証明書 *.example.com を使うことができれば証明書を1つにまとめることができるはずです。 軽く調べてみるとLet's Encryptはワイルドカード証明書に対応していることがわかりました。 やったね! 壁その2: ワイルドカード証明書の取得に関する制限 早速、取得する証明書をワイルドカード形式にしてみることにしました。 certificate.yml apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: example-certificate spec: secretName: certs-example issuerRef: kind: Issuer name: letsencrypt commonName: "*.example.com" dnsNames: - "*.example.com" 結果、これまで上手くいっていた証明書取得は謎のエラーにより動かなくなりました。 彼はふたたび詰みました。 解決策 どうやらLet's Encryptでのワイルドカード証明書の取得には、よりセキュアなチャレンジ方式を用いる必要があるようでした。 彼が使っていたのは最もベーシックな HTTP-01 でしたが、これをより信頼性の高い DNS-01 チャレンジにすることで解決することがわかりました。 cert-managerにはAzure DNSを用いて DNS-01 チャレンジを行うための仕様が用意されていたので、設定してみることにしました。 issuer.yml apiVersion: cert-manager.io/v1 kind: Issuer metadata: name: letsencrypt spec: acme: server: https://acme-v02.api.letsencrypt.org/directory email: hoge@example.com privateKeySecretRef: name: letsencrypt-key solvers: - dns01: azureDNS: environment: AzurePublicCloud subscriptionID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx resourceGroupName: hogehoge hostedZoneName: example.com tenantID: yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy clientID: zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz clientSecretSecretRef: name: azuredns key: azure-client-secret この設定は見事に動き、生成されたワイルドカード証明書がSecretとして保存されました。 よかったね! 壁その3: Secretのスコープ しかしここで彼は気づきました。 「Secretって他の名前空間で使いまわせなくね?」 そう、せっかく作った証明書のSecretですが、これを各名前空間で共通して使うことができないと意味がなかったのです。そして、そんな仕組みは今のKubernetesにはありませんでした。 彼は三たび詰みました。 解決策 彼に残されたのは、たった1つのシンプルな答えでした。 「複数の名前空間で使いまわせなければ、Secretをコピーすればいいじゃない」 そして もはやヤケクソになった 彼は クソ雑な コードを書き上げました。 そう、彼を最後に助けたのはコードを書く腕力でした。 あとはCronJobによる定期実行が全てを解決してくれました。 世界に平和が訪れたのです。 がんばったね! まとめ そんなわけで、ユーザーごとに異なるコンテナを異なるドメインで提供するようなサービス構成を作ってみたら思いのほか苦労したよ!というお話でした。 苦心した甲斐あって今では証明書の調達に悩まされることもなく、安定してサービス提供が出来ていて万々歳です。 ……そして彼はのちに複数の名前空間に分かれた各環境のバージョン管理や運用にてもっと苦労することになるのですが、それはまた別のお話ということで。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ubuntu20.04@wsl2でDockerを使えるようにする(WindowsのDockerDesktopを使いたくない)

WindowsでDockerが使いたいけど、Docker Desktopは使いたくない Ubuntu20.04@wsl2でDocker利用したい(Windows上のDockerDesktopを使いたくない)のでDocker EngineをUbuntu20.04@wsl2にインストールします。 お役に立てたら、LGTMよろしくお願いします。 Ubuntu20.04@wsl2でsystemd(systemctl)を自動起動する こちらの記事を参考にsystemdをPID1で起動できるようにする 実は↑が一番重要。あとは、公式を参考に実施すれば比較的すんなりいきます。 Repositoryをセットアップ $ sudo apt-get update $ sudo apt-get install \ ca-certificates \ curl \ gnupg \ lsb-release $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg $ echo \ "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null # amd64のところはマニュアルだと$(dpkg --print-architecture)。うまくいかなかったので直接amd64としていするとなぜか行けた。 Docker Engineをインストール $ sudo apt-get update $ sudo apt-get install docker-ce docker-ce-cli containerd.io # ちなみにPID1でsystemdが立ちあがっていないとここでインストールできない インストールは完了したので、helloしてみる docker run hello-world #実行結果 docker: Got permission denied while trying to connect to the Docker daemon socket… 実行権限がないと怒られる。 作業中のユーザーに権限を与える 公式を参考に、 $ sudo gpasswd -a $(whoami) docker $ sudo chgrp docker /var/run/docker.sock $ sudo service docker restart 一旦Ubuntuからログアウトしてwslを再起動(wsl --shutdown)して、もう一度Ubuntuにログイン。 その上で再度helloしてみる $ docker run hello-world # 実行結果。中段に下記が出ていればOK Hello from Docker! This message shows that your installation appears to be working correctly. 以降は自動でDockerも立ち上がるようになっており、 これでUbuntu20.04@wsl2上でDockerが使えるようになります。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Docker(Debianベース)でRust+WebAssembly

公式提供のDockerイメージが使えない場合にどうぞ Docker環境でRustの開発を行いたい場合、第一の選択肢として公式がdockerhubに提供してくれているコンテナイメージがあります。 しかし、自分が Rust+WebAssembly 環境を作成しようとした際、公式提供のイメージをベースにするとあれこれ問題が起こりどうにも解決できませんでした。そのためOSのみのイメージをベースに公式が提供しているコマンドを使ってRustを入れ環境構築しようとしたのですが、この対応にあたりまとまった情報がなかなか見つからなかったため、解説もないメモ書き程度のものですが公開だけしておきます。 似たようなことでお困りのかたがいらしたら参考になれば幸いです。 Dockerfile FROM debian:latest RUN apt update -y && apt upgrade -y RUN apt-get install -y curl RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y ENV PATH=/root/.cargo/bin:$PATH RUN apt-get install -y libssl-dev pkg-config build-essential RUN cargo install wasm-pack trunk wasm-bindgen-cli RUN rustup target add wasm32-unknown-unknown 補足 Rustは全体的にインストールが重く、初回ビルドにはけっこう時間かかります。(なお上記の公式imageのpullもまあまあ時間がかかります) 30分〜1時間くらいは許容範囲ですので、時間がかかっても焦らず気長にお待ちください。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

DockerでYew(Rust+WebAssembly)環境を構築

公式提供のDockerイメージが使えない場合にどうぞ Docker環境でRustの開発を行いたい場合、第一の選択肢として公式がdockerhubに提供してくれているコンテナイメージがあります。 しかし、自分がRust+WebAssemblyのアプリ作成のためにYewというフレームワーク用の環境を作成しようとした際、公式提供のイメージをベースにするとあれこれ問題が起こりどうにも解決できませんでした。そのためOSのみのイメージをベースに公式が提供しているコマンドを使ってRustを入れ環境構築しようとしたのですが、この対応にあたりまとまった情報がなかなか見つからなかったため、解説もないメモ書き程度のものですが公開だけしておきます。これでチュートリアルくらいは突破できると思います。 似たようなことでお困りのかたがいらしたら参考になれば幸いです。 Dockerfile FROM debian:latest RUN apt update -y && apt upgrade -y RUN apt-get install -y curl RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y ENV PATH=/root/.cargo/bin:$PATH RUN apt-get install -y libssl-dev pkg-config build-essential RUN cargo install wasm-pack RUN cargo install trunk wasm-bindgen-cli RUN rustup target add wasm32-unknown-unknown 補足 Rustは全体的にインストールが重く、初回ビルドにはけっこう時間かかります。(なお上記の公式imageのpullもまあまあ時間がかかります) 30分〜1時間くらいは許容範囲ですので、時間がかかっても焦らず気長にお待ちください。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【docker】herokuへのデプロイ作業で、No images to pushと表示される

No images to pushと表示されてしまう エラー内容 herokuにdocker環境で作成したアプリをpushしようとした際に上記のエラーを吐いてしまった。 $ heroku container:login Login Succeeded $ heroku create アプリ名 Creating ⬢ アプリ名... done https://アプリ名.herokuapp.com/ | https://git.heroku.com/アプリ名.git $ heroku container:push web ▸ No images to push 状況整理 ディレクトリ構成は下記のようになっており、SRCディレクトリにrailsアプリのファイル群が格納されており、SRCディレクトリと同じディレクトリにdocker-compose.ymlなどのDocker用ファイルを配置しておりました。 SRC |-APP |-bin ... docker-compose.yml dockerfile entrypoint.sh 原因解明と解決方法について dockerfileなどの内容と配置に問題はなかったのですが、ファイル名が原因でした。 誤)dockerfile 正)Dockerfile Dockerfileの頭文字が大文字になっていなかったため発生したことがわかりました。修正後にheorku container:push webを実行したところ無事にpushできました。 何を言いたいかというと、Dockerfileのファイル名が誤りでもDockerfileとして認識していればちゃんとDockerが動くあたりすごいなと。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[VSCode]Remote Containersで開発環境を効率的に作成する

RemoteContainerとは? VSCodeでコンテナ開発環境(devcontainer)を作成するための拡張機能 Remote - Containers - Visual Studio Marketplace 利点 Dockerで開発する利点とVSCodeで開発する利点のどちらも享受できる Dockerで開発する利点 OS依存がない 特定の人だけ実行できないなどの環境依存がない 使用するライブラリなどのバージョンが統一される VSCodeで開発する利点 Linter、Formetterなどの設定をプロジェクトで共通化 それらの設定の自動適用 開発で使用するVSCode拡張機能を自動インストール 開発するのに必須な拡張機能などをプロジェクトで統一可能(Vue.jsで言うところのVeturなど) 開発環境構築毎に、拡張機能を入れるのでHOST汚染がない 欠点 VSCodeを使用していないと使えない 使い方 RemoteContainersのインストール code --install-extension ms-vscode-remote.remote-containers RemoteContainerの起動方法 VSCodeでcommand+Shift+Pを入力後、Remote-Containers: Add Development Container Configuration Filesと入力 何のDocker環境を構築するか選択する画面になるので、Python3を選択します その後は適当に最新版を選択後、OKを押下するとdevcontainer.jsonが作成されます 先程までなかった.devcontainerが作成されているはずなので、VSCodeでcommand+Shift+Pを入力後、Remote-Containers: Open Folder in Containerと入力 .devcontainerが存在するディレクトリでOKを押下 VSCodeが新規画面を開き、コンテナをビルドするのでしばらく待つ ビルドが完了するとVSCodeの左下にDEV Containerと表示され、VSCodeでコンテナ内に入っていることがわかります TeminalもDocker内部なので、最新版のPythonがインストールされていることがわかります - ログインユーザーもvscodeになっています 以上でRemoteContainerの起動成功です 説明 devcontainer.jsonでRemoteContainerの設定を行っているので内容を解説します devcontainer.json { "name": "Python 3", "build": { "dockerfile": "Dockerfile", "context": "..", "args": { "VARIANT": "3.10-bullseye", "NODE_VERSION": "lts/*" } }, "settings": { "python.defaultInterpreterPath": "/usr/local/bin/python", "python.linting.enabled": true, "python.linting.pylintEnabled": true, "python.formatting.autopep8Path": "/usr/local/py-utils/bin/autopep8", "python.formatting.blackPath": "/usr/local/py-utils/bin/black", "python.formatting.yapfPath": "/usr/local/py-utils/bin/yapf", "python.linting.banditPath": "/usr/local/py-utils/bin/bandit", "python.linting.flake8Path": "/usr/local/py-utils/bin/flake8", "python.linting.mypyPath": "/usr/local/py-utils/bin/mypy", "python.linting.pycodestylePath": "/usr/local/py-utils/bin/pycodestyle", "python.linting.pydocstylePath": "/usr/local/py-utils/bin/pydocstyle", "python.linting.pylintPath": "/usr/local/py-utils/bin/pylint" }, "extensions": [ "ms-python.python", "ms-python.vscode-pylance" ], "forwardPorts": [], "postCreateCommand": "pip3 install --user -r requirements.txt", "remoteUser": "vscode" } 各設定項目 name RemoteContainerの環境名 build どのファイルを元にコンテナをビルドするか設定 dockerfile Dockerfileを指定。相対パスなどで指定可能 dockerComposeFile docker−composeを使用する場合、dockerfileではなく、こちらで設定する context ビルドを行う相対パスの指定 args "args": {"NODE_VERSION": "lts/*"}のようにしてコンテナ内に設定したい環境変数を指定 settings VSCodeの設定を記載。command + ,を使用した時の設定内容のJSON ここで適切な設定を行うことで、LinterやFormetterをVSCode保存時自動実行などが可能になる extensions VSCodeの拡張機能のIDを記載すれば、RemoteContainer起動時にコンテナ内に自動的にインストールされる 拡張機能のIDは拡張機能インストール画面で設定からコピー可能 自分のVSCodeで使用している拡張機能IDを一括で出力する場合のコマンド code --list-extensions | xargs -L 1 echo code --install-extension forwardPorts portを開ける postCreateCommand コンテナ起動後に、自動実行したいコマンドなどを入力できる remoteUser コンテナのログインユーザーの指定。デフォルトはvscode homebrewなどを使用する際にはAdmin権限でコンテナを使用できないので必要 docker-composeでRemoteContainer 説明ではDockerfile単体でRemoteContainerを起動する方法を説明致しましたが、下記のリポジトリのように、docker-composeでRemoteContainerを起動することも可能です selenium-docker-env/devcontainer.json at main · I-s-23/selenium-docker-env devcontainerで環境変数を定義 .envファイルを読み込ませる devcontainer.jsonに以下のように書けば、Docker内部で環境変数が読み込まれます VSCodeのdevcontainer.jsonのremoteEnvでハマった話 | by GALACTIC1969 | GALACTIC1969 | Medium devcontainer.json "runArgs": [ "--env-file", ".env" ], envファイルを使わない場合、このように定義することも可能です devcontainer.json "runArgs": [ "-e BIND_PORT=80", "-e BIND_ADDRESS=0.0.0.0", "-e BIND_ADDRESS=${ADRESS}", ], マルチステージングビルド マルチステージングビルドの環境もRemoteContainerで開けます 以下のようにdevとprodでマルチステージングビルドをする場合、docker-compose.yamlにtarget: devと書いた状態でRemoteContainerを起動すれば、devのTagrgetでビルドが止まるので開発が可能になります FROM python:3.10 as dev ENV APP_HOME /workspace WORKDIR $APP_HOME COPY . . RUN python -m pip install -U pip setuptools \ && pip install -r requirements.txt \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* FROM python:3.10-slim-buster as prod COPY . . COPY --from=dev /root/.cache/pip /root/.cache/pip COPY --from=dev /workspace/requirements.txt . RUN python -m pip install -U pip setuptools \ && pip install -r requirements.txt docker-compose.yaml version: "3.9" services: auto: build: context: ../ dockerfile: Dockerfile target: dev env_file: .env tty: true stdin_open: true ports: - 8099:8099 volumes: - ..:/workspace:cached 自分が今まで作成したdevcontainer 個人開発で使用している物なのでご自由にお使い下さい IaC I-s-23/IaC-env at develop Terraform,aws-cli,cloudSDKなどIaCを行いたい場合などに役立たせて下さい React I-s-23/react-docker-development-environment Python Selenium I-s-23/selenium-docker-env: Selenium web browser automation docker env andmy custom functions Python3.9+Selenium+ChromeDriver+pyautoGUIが入ったDocker環境です。ブラウザの自動操作にお使い下さい Go I-s-23/golang-docker-dev: golang dev docker with VS Code extend remote-containers SAM I-s-23/sam-local-invoke-in-docker AWS Lambdaをlocalでテスト実行可能になっている環境 Features RemoteContainersにfeaturesというPreview機能が追加されました 簡単に説明するとdevcontainer.jsonに以下のような記載をするだけで、その機能が使用可能という物です 例. devcontainer内でGitとGitHubCLIの最新版を使用したい場合 devcontainer.json  "features": { "git": "latest", "github-cli": "latest" } 以下が現状featuresで対応している機能です Terraform、Docker in Docker などIaCに必要な物が用意されているのは嬉しいですね その他、GitHubCLI、homebrewなど最新版のインストールが地味に面倒な物をこの設定だけでインストールできるのが有り難いです devcontainer.json "features": { "docker-in-docker": "latest", "docker-from-docker": "latest", "kubectl-helm-minikube": "latest", "terraform": "latest", "git": "latest", "github-cli": "latest", "azure-cli": "latest", "sshd": "latest", "desktop-lite": "latest", "homebrew": "latest", "python": "latest", "golang": "latest", "java": "lts", "maven": "latest", "gradle": "latest", "ruby": "latest", "rust": "latest", "powershell": "latest" } この機能の注意点として、対応していないBaseコンテナがあること(homebrewをfeaturesでDebian、AmazonLinux2などにインストールしようとするとエラーになる) もう1点、featuresはコンテナの構築後にインストールされる仕様なのか、featuresでhomebrewなどをインストールした場合、Dockerfile内でRUN brew installなどを行うとエラーになります コンテナ内にhomebrewがない段階でbrew installを行おうとしたからだと思われる featuresの詳細に関しては詳しく書かれている方がいらっしゃいますのでそちらを参考にしてください Dev container features (preview) が便利すぎる - Qiita 感想 RemoteContainersは.devcontainerをリポジトリにPushしなければ個人で利用することも可能で、Pushしてチームで共有すれば、開発環境をチームで展開できる。など自由度が高いところがいいところだと思っております refarence Dev container features (preview) が便利すぎる - Qiita VSCode Remote Containers を利用して最強のローカル開発環境を作りたい - Qiita
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

複数のプロジェクトで Docker を使用する場合の個人的ベストプラクティス

社内でDockerを利用したプロジェクトが増えてきて、ポートの競合問題やコンテナが多すぎて重いなどの問題があり、「ひとまず現状これがベストかな?」と思える設定に落ち着いたので、それを書く。 概要 DB や mailhog などの共通で利用できるコンテナは共通化し、DBなどのポート競合や起動コンテナを減らす nginx-proxy でリバースプロキシして web のポート競合も回避する laravel のプロジェクトでしか私は使用していないが、汎用性はあると思う 注意 DBを共有にするため、プロジェクト毎にDBのバージョンを分けたい場合には対応できない。 そういった場合は、 律儀に、ポート番号が被らないように各プロジェクトで設定するか ループバックアドレスをプロジェクト毎に割り当てるか (https://qiita.com/hanlio/items/243006a67fb8d535d958) で対応が可能です。 ディレクトリ構成 . ├── webdev │   ├── dump/ │   └── docker-compose.yaml ├── project1 │   ├── docker-compose.yaml │   └── etc... └── project2    ├── docker-compose.yaml    └── etc... 共通コンテナの設定 adwin さんが公開してくれているリポジトリに nginx-proxy を追加いただけ。 https://github.com/adwinying/webdev docker-compose.yaml docker-compose -d pgsql mailhog proxy と必要なコンテナのみ起動する ダンプファイルなどがあれば、dump ディレクトリを作成して、そこにダンプファイルを格納する version: '3' services: mysql: image: mysql:5.7 ports: - '${MYSQL_PORT:-3306}:3306' environment: MYSQL_ROOT_PASSWORD: '${DB_PASSWORD:-password}' MYSQL_DATABASE: '${DB_DATABASE:-db}' MYSQL_USER: '${DB_USERNAME:-sail}' MYSQL_PASSWORD: '${DB_PASSWORD:-password}' MYSQL_ALLOW_EMPTY_PASSWORD: 'yes' volumes: - 'webdev-mysql:/var/lib/mysql' - './dump:/tmp/dump' networks: - webdev healthcheck: test: ["CMD", "mysqladmin", "ping", "-p${DB_PASSWORD:-password}"] retries: 3 timeout: 5s pgsql: image: postgres:13 ports: - '${PGSQL_PORT:-5432}:5432' environment: PGPASSWORD: '${DB_PASSWORD:-password}' POSTGRES_DB: '${DB_DATABASE:-db}' POSTGRES_USER: '${DB_USERNAME:-sail}' POSTGRES_PASSWORD: '${DB_PASSWORD:-password}' volumes: - 'webdev-pgsql:/var/lib/postgresql/data' - './dump:/tmp/dump' networks: - webdev healthcheck: test: ["CMD", "pg_isready", "-q", "-d", "${DB_DATABASE:-db}", "-U", "${DB_USERNAME:-sail}"] retries: 3 timeout: 5s redis: image: 'redis:alpine' ports: - '${REDIS_PORT:-6379}:6379' volumes: - 'webdev-redis:/data' networks: - webdev healthcheck: test: ["CMD", "redis-cli", "ping"] retries: 3 timeout: 5s meilisearch: image: 'getmeili/meilisearch:latest' ports: - '${MEILISEARCH_PORT:-7700}:7700' volumes: - 'webdev-meilisearch:/data.ms' networks: - webdev mailhog: image: 'mailhog/mailhog:latest' ports: - '${MAILHOG_PORT:-1025}:1025' - '${MAILHOG_DASHBOARD_PORT:-8025}:8025' networks: - webdev proxy: image: jwilder/nginx-proxy container_name: nginx-proxy ports: - "127.0.0.1:80:80" volumes: - /var/run/docker.sock:/tmp/docker.sock:ro restart: always privileged: true networks: - webdev networks: webdev: name: webdev driver: bridge volumes: webdev-mysql: driver: local webdev-pgsql: driver: local webdev-redis: driver: local webdev-meilisearch: driver: local プロジェクト毎の設定 共通コンテナを立ち上げた後、プロジェクト毎では web のコンテナだけ起動すれば良い docker-compose.yaml ports は 80 だけ指定すれば、コンテナ側のポートは適当に割り当ててくれる environment に VIRTUAL_HOST を設定することで、http://laravel.test にアクセスした際、nginx-proxy がよしなにしてくれる 共通コンテナと同一ネットワークに所属する必要があるので、 networks に webdev を指定している version: '3' services: app: image: thecodingmachine/php:7.4-v4-apache ports: - '80' environment: PHP_EXTENSIONS: bcmath gd intl pdo_pgsql pgsql PHP_INI_MEMORY_LIMIT: 512M PHP_INI_DATE__TIMEZONE: Asia/Tokyo PHP_INI_MBSTRING__LANGUAGE: Japanese APACHE_DOCUMENT_ROOT: /var/www/html/public VIRTUAL_HOST: 'laravel.test' volumes: - '.:/var/www/html' networks: - webdev networks: webdev: external: true name: webdev hosts ファイル hostsファイルに、 VIRTUAL_HOST の値を追記。 127.0.0.1 laravel.test おまけ 少しズレるが、docker-compose コマンドが長すぎるので、Taskfile の設定も置いておきます。 使用手順 docker-compose.yaml と同一階層に置く chmod 755 ./Taskfile で権限を変更する alias task=./Taskfile などとエイリアスを設定する これで準備完了です。 task artisan migrate などで実行できるので便利! Taskfile #!/bin/bash # https://github.com/adriancooney/Taskfile#install function up { docker-compose up -d } function down { docker-compose down } function restart { docker-compose restart } function exec { docker-compose exec app "$@" } function bash { exec bash } function php { exec /usr/bin/php "$@" } function artisan { exec /usr/bin/php artisan "$@" } function composer { exec /usr/local/bin/composer "$@" } function test { exec vendor/bin/phpunit "$@" } function tinker { artisan tinker } function start { echo "start task not implemented" } function default { help } function help { echo "$0 <task> <args>" echo "Tasks:" compgen -A function | cat -n } TIMEFORMAT="Task completed in %3lR" time ${@:-default} 本記事は個人ブログからの転記です。 https://zumikiti-note.netlify.app/posts/docker-multi-up/
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

docker-compose.ymlのversionについて

結論 version: '3.8' services: web: ... db: ... のように、docker-compose.yml の一番上に、versionを指定している記事がよく見られますが、 このvesion表記は実はdeprecated (非推奨)であり、現在は一切使用されていない値になります。 なので、書くときやコピペする時は書く必要はありません。 詳しく見ていく docker-composeの仕様を定めている compose-spec を読むと、Compose fileの章でversionにDEPRECATEDを書いてあります。 理由を見るとこう書いてあります。 下記は意訳になります。 トップレベルにおけるversionプロパティは、後方互換性のために仕様で定義されたプロパティですが、現在は参考程度(=コメント)にしかなりません。 Composeの実装は、この値を使用してCompose fileを検証するための正確なスキーマを決めてはいけません。常に、設計された時点での最新のスキーマを選択すべきであります。 とかかれています。 おわりに 何かといろんな記事で見かけるdocker-compose.ymlのversionですが、必要ないなら書かなくても良いかと思います。 コメント程度に残しておく分には良いかもしれませんね。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

エッジデバイスでAIを現場に! ~Jupyter NotebookでDocker上のOpenVINOを試す~

はじめに 概要 この記事では、日立のエッジ製品CE50-10Aを用いたAIアプリケーションの開発の初歩(Hello Worldレベル)の手順をご説明します。 この手順に従うことで、高度な知識が求められる学習モデルの作成や環境セットアップといった作業をスルーして、初歩的なAIアプリケーションの開発を体験することができます。 読者としては、あまりAIに馴染みのない方を想定しています。 CE50-10Aとは CE50-10Aは、工場や発電所のような産業・インフラ業界におけるAI活用を念頭に、日立が2021年に販売開始したエッジ製品です。 引用元:https://www.hitachi.co.jp/products/it/control_sys/platform/cs_edge/index.html IntelのAI推論フレームワーク OpenVINO をプレインストールしており、すぐに開発を始めることができます。 また、粉塵や振動、多湿といった過酷な環境に耐えうる堅牢な構造により、幅広い現場で長期に渡る利用が可能です。 OpenVINOとは OpenVINOとは、Intelが提供するフリーのAI推論の開発フレームワークです。 Intel製のCPUやGPUで推論処理を高速に実行することができます。 OpenVINOは、C/C++やPythonから利用可能ですが、CE50-10AではPythonからの利用をサポートしています。 CE50-10Aが提供する機能 CE50-10Aは、単にOpenVINOをプレインストールしているだけでなく、AIアプリケーションの開発/運用を効率よく・確実に行えるように複数の機能を提供しています。 具体的には、 複数の種類のカメラデバイスに対応し、アプリケーション側でその違いに対応する必要を無くすデータ入力機能 データをキャッシュして状態を管理するデータ管理機能 現場に配備(=再頒布)する時問題となる、OSSや動画コーデックなどのライセンスに対応した推論実行機能 OpenVINO上のアプリ開発を手軽に体験出来る推論開発機能 などです。 本記事では、「推論開発機能」について、実際に操作を体験していきます。 推論開発機能を使ってみる 推論開発機能は、Dockerコンテナ上にセットアップされたOpenVINOとJupyter Notebookを提供するものです。 Jupyter Notebookは、PythonなどをWebブラウザ上で記述・実行出来る開発環境です。 入力したプログラムをすぐに実行したり、実行結果を確認できるので非常に便利です。 この章で出来ること 監視カメラの映像に映っている自動車の位置を検出してみます。 引用元:https://github.com/intel-iot-devkit/sample-videos/blob/master/preview/car-detection.gif 結果がこのように表示されます。 これを応用すれば、例えば、 通過した自動車の台数をカウントしたい 自動車が写っているときだけ録画したい といったユースケースで使うことができるでしょう。 準備するもの 以下のファイルをダウンロードしておきます。 サンプル動画ファイル 入力となる動画ファイルです。 https://github.com/intel-iot-devkit/sample-videos/blob/master/car-detection.mp4 学習済みモデルファイル 自動車を検出できるように、あらかじめ学習させたニューラルネットワークのファイルです。 IntelはOpen Model Zooというサイトで様々な学習済みモデルファイルを配布しています。 https://download.01.org/opencv/2020/openvinotoolkit/2020.3/open_model_zoo/models_bin/1/vehicle-detection-adas-0002/FP32/ 環境のセットアップ CE50-10Aと操作用のPCを同じネットワークに接続します。 また、Dockerが利用可能なようにセットアップしておきます。セットアップ方法はユーザーズガイドの3章を参照してください。 Dockerコンテナの起動 推論実行機能はDockerコンテナとして実行されます。 以下のコマンドを実行します。 $ sudo docker run -it --rm -p 8888:8888 ctrl_edge_ai/openvino_devel:1.0 以下のようにURLが表示されます。 Copy/paste this URL into your browser when you connect for the first time, to login with a token: http://0.0.0.0:8888/?token=66b5d8ca82cac0134b3af02709acb1cf8d521ec17e6016da このURLの0.0.0.0を、CE50-10Aに設定したIPアドレスに置き換えて、作業用PCのブラウザで開きます。 以下のようにJupyter Notebookの画面が表示されます。 ファイルのアップロード 「準備するもの」でダウンロードしたファイルをアップロードしていきます。 [Upload]をクリックします。 ファイル選択ダイアログが表示されたら、アップロードするファイルを開きます。 以下のようにファイル名が表示されるので、表示されたファイル名の右にある[Upload]をクリックすると、ファイルがアップロードされます。 Notebookの作成 [New]をクリックし、[Python3]をクリックします。 以下のようにNotebookが開きます。 プログラムの入力と実行 いよいよプログラムの入力と実行をしていきます。 ライブラリのインポート まずは使用するライブラリをインポートします。 import cv2 import matplotlib.pyplot as plt from openvino.inference_engine import IECore import numpy as np 上のコードをNotebookにコピー&ペーストして、Shift+Enterを実行します。すると、入力したプログラムが実行されます。 以降も同様に (1)プログラムをコピー&ペースト (2)Shift+Enterでプログラムを実行 を実施してください。 動画ファイルのオープン 動画ファイルを読み込みます。 2行目では、動画の200コマ目から画像を読み出すよう設定しています。自動車が映っているタイミングを選ぶためです。 cap=cv2.VideoCapture("car-detection.mp4") cap.set(cv2.CAP_PROP_POS_FRAMES,200) 画像の読み出しとプレビュー 読み込んだ動画の画像をJupyter Notebook上で確認してみます。 ret,img=cap.read() plt.imshow(cv2.cvtColor(img,cv2.COLOR_BGR2RGB)) 以下のようにJupyter Notebook上に画像が表示されます。 学習済みモデルの読み込み 学習済みモデルのファイルを読み込みます。 OpenVINOでニューラルネットワークの推論を行うInference Engineのインスタンスを生成して、 そこにモデルファイルを読み込ませます。 load_network関数のパラメータで、推論を実行するデバイスを指定します。 ここでは"CPU"としていますが、ここを"GPU"にするだけでGPUで実行できます1。 model_xml="vehicle-detection-adas-0002.xml" model_bin="vehicle-detection-adas-0002.bin" ie=IECore() net=ie.read_network(model=model_xml,weights = model_bin) exec_net=ie.load_network(network=net,device_name="CPU") 画像の変換 取得した画像を推論できるように変換します。 n, c, h,w = net.inputs['data'].shape ih, iw = img.shape[:-1] input_img = cv2.resize(img,(w,h)) input_img=input_img.transpose((2,0,1)) data={} data['data']=input_img 推論を実行 いよいよ推論を実行します。 学習済みモデルを読み込んだInference Engineのインスタンスに、変換した画像データを入力すると、結果が出力されて変数resに格納されます。 res=exec_net.infer(inputs=data) 推論結果を確認 推論結果を表示させてみます。 res['detection_out'][0][0][0] この数値が、画像上で自動車が存在する場所の座標などの情報を示しています。 推論結果を表示 このままではよくわからないので、推論結果を表示させてみます。 推論結果は、自動車のある位置の左上・右下のそれぞれの位置を画像の幅・高さを1とした割合で示しています。 forにより推論結果から、1件ずつ自動車のある位置を取り出し、OpenCVのrectangle関数で、その座標に白い枠を描画しています2。 for number, proposal in enumerate(res['detection_out'][0][0]): xmin = np.int(iw * proposal[3]) ymin = np.int(ih * proposal[4]) xmax = np.int(iw * proposal[5]) ymax = np.int(ih * proposal[6]) img = cv2.rectangle(img, (xmin,ymin),(xmax,ymax),(255,255,255),2) plt.imshow(cv2.cvtColor(img,cv2.COLOR_BGR2RGB)) 自動車の位置を囲んで表示することができました。 まとめ CE50-10Aに搭載された推論開発機能を用いて、Docker上に構築したOpenVINOをJupyter Notebookで操作する手順を示しました。 上記に沿って実施することで、初歩的なAIアプリケーションの開発を体験することができます。 CE50-10Aについての詳しい情報は以下のサイトをご覧ください。 https://www.hitachi.co.jp/products/it/control_sys/platform/cs_edge/index.html 免責・商標類 本記事に記載した手順は、その動作や結果を保証するものではありません。 製品の改良により、予告なく記載されている仕様が変更になる場合があります。 本記事に記載の会社名、製品名などは、それぞれの会社の商標もしくは登録商標です。 実際にはコンテナ上のプログラムがGPUにアクセスできるようにDockerの設定が必要です。 ↩ 実際には、座標に加えて(1)バッチ処理時の画像ID(2)画像のクラス(3)confidence(推論結果の確からしさ)が返されます。プログラムを単純化するための省略していますが、閾値未満のconfidenceの座標は描画しないといった処理の検討が必要です。 ↩
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む