20210114のdockerに関する記事は7件です。

【個人的に】Dockerがはかどる小技

初めて知ったときは感動したけど 自分の中で知ってて当然になってしまった小技をまとめました
まだこの小技を知らない人に届いてくれるとうれしい

Dockerfile

RUNを1つにまとめる

Dockerfile
RUN echo '1つ目のコマンド'
RUN echo '2つ目のコマンド'

&& を使って1つにまとめる

Dockerfile
RUN echo '1つ目のコマンド' && echo '2つ目のコマンド'

&& はDockerの小技というよりシェルの機能です
不用意にイメージレイヤーを増やすと イメージサイズが大きくなってしまうので RUNはなるべく1つにまとめた方が良い

RUNで条件分岐

Dockerfile
ARG HOGE="hoge"

RUN if [ "$HOGE" = "hoge" ]; then \
      echo 'hoge'; \
    fi

これもDockerの小技というよりシェルの機能です
特定のビルド引数が入ってきたときにのみ実行したい処理があるときに便利です

:warning: 使いどころに注意
そのイメージの本質が変化してしまうような使い方はあんまり良くないです。
ちょっとしたツールを入れたりオプショナルな使い方がおすすめです

別のイメージからファイルをCOPYする

Dockerfile
COPY --from=composer:2.0 /usr/bin/composer /usr/bin/composer

特定のコマンドを持ってくるときに便利
自前でインストールするコマンドを書かなくても 公式のイメージから持ってこれる安心感

環境によってCOPYするファイルを変える

Dockerfile
ARG TARGET_ENV

COPY ./docker/nginx/$TARGET_ENV/nginx.conf /etc/nginx/nginx.conf
docker/
  nginx/
    dev/
      nginx.conf
    ci/
      nginx.conf
    pro/
      nginx.conf

ただビルド引数を使っているだけですが ディレクトリを分けて環境ごとの設定を書いておくことで 開発環境、テスト環境、本番環境などの切り替えが楽になります

マルチステージビルド

Dockerfile
FROM nginx AS MOUNT

# some code

FROM MOUNT AS BUNDLE

# カレントディレクトリを丸ごと /usr/share/nginx/html にコピーする
COPY . /usr/share/nginx/html

イメージをビルドするときに --target string を指定してどこまでビルドするのか選べます

docker build --target MOUNT . にすると /usr/share/nginx/html にはなにも入ってない状態
コンテナ起動するときにマウントして開発できる

docker build --target BUNDLE . にするとイメージにコードが含まれているのでそのままコンテナを実行できる

みたいな使い方できます

DockerCompose

.env

.env
NGINX_PORT=80

docker-compose.yml は 環境変数を使用することができ、 .env ファイルにも対応しています

docker-compose.yml
version: '3.8'

services:
  nginx:
    image: nginx
    ports:
      - ${NGINX_PORT}:80

人によって設定を変えたいような項目は .env に書き出しておくと便利

「80番ポート他でもう使ってるよ」ってことがあるのでホスト側のポートは 変数 にしがち

docker-compose.override.yml

docker-compose.ymlの設定を上書きできるファイル

docker-compose.yml

docker-compose.yml
version: '3.8'

services:
  php:
    image: php
    ports:
      - 80:80

docker-compose.override.yml

docker-compose.override.yml
version: '3.8'

services:
  php:
    volumes:
      - ${APP_DIR}:/app
      - php_vendor:/app/vendor
    depends_on:
      - mysql

  mysql:
    image: mysql
    volumes:
      - mysql_data:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=${DB_PASS}

volumes:
  mysql_data:
  php_vendor:

ローカルだけ docker-compose.override.yml を作ってデータベースのコンテナを用意する
みたいな使い方ができます

その他

.dockerignore

COPY するときに除外したいファイルやフォルダを指定するファイル

.dockerignore
.vscode
.env
.git
.gitignore
.gitattributes
**/.gitkeep
**/Dockerfile
docker-compose.yml
docker-compose.override.yml

host.docker.internal

コンテナからホストマシンのIPアドレスを指定したいときに使う

XDebug のようなデバッグツールの設定でつかったり

php.ini
[xdebug]
xdebug.client_host=host.docker.internal
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【AWS ECR】Dockerイメージの保存と取得

目標

AWS ECRを利用したDockerコンテナレジストリ上にDokcerイメージの保存及び取得を実施する。

はじめに

以下Youtube動画(by くろかわこうへい氏)に沿ってハンズオンを実施した結果をアウトプットとして記載致しました。
AWS ECRに関する基本事項は以下のリンクより学習することが出来ます。

今から追いつくDocker講座!AWS ECSとFargateで目指せコンテナマスター!〜シリーズ3回目〜

前提

・Dockerデーモンが起動しているEC2インスタンス(Amazon Linux2)が構築済みであること(※)。

※以下記事の手順1「Dockerデーモン起動」までを完了すれば前提は整います。
【Docker】dockerfileを利用してEC2にApacheコンテナを構築(Dockerデーモン起動)

作業の流れ

項番 タイトル
1 ECRの構築
2 ECRアクセス用IAMロールアタッチ
3 ECRにDockerイメージを保存する
4 ECRからDockerイメージを取得する

手順

1.ECRの構築

ECRコンソールからレポジトリ作成を開始します。tempsnip.png

レポジトリ名を入力し(本記事ではtestrepoとしました)、下段にあるレポジトリ作成実行ボタンをクリック
tempsnip.png
tempsnip.png

レポジトリが正常に構築されました。
image.png

2.ECRアクセス用IAMロールアタッチ

EC2からECRへアクセスするための権限を付与するため、IAMロールの作成、及び対象EC2インスタンスへのアタッチを実施します。

IAMロールコンソールからロールの作成をクリック
tempsnip.png

今回はIAMロールをEC2にアタッチするため、EC2を信頼されたエンティティとして設定します。
tempsnip.png

ECRへのフルアクセス権を付与するIAMポリシーAmazonEC2ContainerRegistryFullAccessをIAMロールに埋め込みます。
tempsnip.png

IAMロール名を記載(本記事ではecr-accessと設定)しロールの作成を実行します。

tempsnip.png

作成したIAMロールを対象のEC2インスタンスへアタッチします。
tempsnip.png

tempsnip.png

3.ECRにDockerイメージを保存する

対象のEC2インスタンスへOSログイン(ルートユーザ前提として記載します)し、dockerfileの記載を行います。

サンプルとして、httpdをインストールし、コンテナ起動時にhttpdを自動起動するDockerイメージを作成するような処理を記述します。

dockerfile
FROM centos:centos7

RUN yum -y install httpd

CMD ["/usr/sbin/httpd","-DFOREGROUND"]

次にECRコンソールに戻り、作成したECRレポジトリを選択しプッシュコマンドの表示をクリックします。
tempsnip.png

すると対象のECRレポジトリにプッシュを行うために一連のコマンドが表示されます。
これらを順に実行していく流れとなります。

image.png

まずは上記プッシュコマンド群の1番目をコピーして実行します。
内容はECRレポジトリへのログインパスワードを取得し、そのパスワードを標準入力としてdocker loginを実行するという内容です。

Login Succeededと表示されればOKです。(IAMロールの設定等が誤っているとcredential系のエラーが表示されます)

[root@ip-172-31-35-94 ~]# aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin 932699493995.dkr.ecr.ap-northeast-1.amazonaws.com
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

2番目のコマンドは通常のdocker buildコマンドです。

docker build -t testrepo .

3番目のコマンドでECRレポジトリプッシュに必要なタグ付けをdocker tagで実施します。

[root@ip-172-31-35-94 ~]# docker tag testrepo:latest 932699493995.dkr.ecr.ap-northeast-1.amazonaws.com/testrepo:latest
[root@ip-172-31-35-94 ~]# docker images
REPOSITORY                                                   TAG                 IMAGE ID            CREATED             SIZE
932699493995.dkr.ecr.ap-northeast-1.amazonaws.com/testrepo   latest              306adf672fc7        10 minutes ago      330MB
testrepo                                                     latest              306adf672fc7        10 minutes ago      330MB
centos                                                       centos7             8652b9f0cb4c        2 months ago        204MB

4番目のコマンドで実際にdocker pushを実行します。

[root@ip-172-31-35-94 ~]# docker push 932699493995.dkr.ecr.ap-northeast-1.amazonaws.com/testrepo:latest
The push refers to repository [932699493995.dkr.ecr.ap-northeast-1.amazonaws.com/testrepo]
9cdaef33df63: Pushed
174f56854903: Pushed
latest: digest: sha256:33f3b20422ea489ca61be9a5b4334b0a68572989b4143bca3cb6d55825c2c07c size: 741

aws ecr describe-images --repository-name リポジトリ名 --region ap-northeast-1を実行し、プッシュしたイメージが確認出来ればOKです。

[root@ip-172-31-35-94 ~]# aws ecr describe-images --repository-name testrepo --region ap-northeast-1
{
    "imageDetails": [
        {
            "artifactMediaType": "application/vnd.docker.container.image.v1+json",
            "imageSizeInBytes": 135861914,
            "imageDigest": "sha256:33f3b20422ea489ca61be9a5b4334b0a68572989b4143bca3cb6d55825c2c07c",
            "imageManifestMediaType": "application/vnd.docker.distribution.manifest.v2+json",
            "imageTags": [
                "latest"
            ],
            "registryId": "932699493995",
            "repositoryName": "testrepo",
            "imagePushedAt": 1610607670.0
        }
    ]
}

4.ECRからDockerイメージを取得する

ECRコンソールから、ECR内に保存されているDockerイメージのURLをコピーします。
tempsnip.png

コピーしたURLをdocker pullコマンドの引数として実行します。

[root@ip-172-31-35-94 ~]# docker pull 932699493995.dkr.ecr.ap-northeast-1.amazonaws.com/testrepo:latest
latest: Pulling from testrepo
Digest: sha256:33f3b20422ea489ca61be9a5b4334b0a68572989b4143bca3cb6d55825c2c07c
Status: Downloaded newer image for 932699493995.dkr.ecr.ap-northeast-1.amazonaws.com/testrepo:latest
932699493995.dkr.ecr.ap-northeast-1.amazonaws.com/testrepo:latest
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails6にDockerを導入したのでまとめてみた(初学者)

目的

ポートフォリオ実装してdockerを導入したのでアウトプットします。
Dockerがなんなのかわからなかったので色々な方のQiitaを参考にしております

Dockerのインストール

私はこの方の記事を見てインストールしました!!
https://qiita.com/kurkuru/items/127fa99ef5b2f0288b81
インストールできたら以下コマンドを実行します。

 % docker run -d -p 80:80 docker/getting-started

インストールの確認

% docker -v

このようなコマンドが出たらインストール完了です。
Docker version 20.10.2, build 2291f61

% docker-compose -v

こちらも同様にdocker-compose version 1.27.4, build 40524192が出力されたら完了です。

Docker導入に渡って

メリットとしてはローカル環境に構築したrailsとmysqlを1コマンド叩くだけで実行できるようになる。と記載されていたのですが、初学者の私には理解が難しかったです。dockerを導入した後にこの意味がわかったのでまずは手を動かした方がいいです。

開発中のアプリでdockerを導入

早速ですが導入していきます。
フレームワークはRubyonRails6を使用しています。

Dockerfileの作成

手順としてDockerを導入したい開発中のアプリに移動します

~ % cd アプリ名
アプリ名 % touch Dockerfile

Dockerfileが作成されたので下記を記載してください。

FROM ruby:2.6.5 

RUN apt-get update -qq && \
    apt-get install -y build-essential \
                       libpq-dev \
                       nodejs

RUN mkdir /アプリ名
WORKDIR /アプリ名

ADD ./Gemfile /アプリ名/Gemfile
ADD ./Gemfile.lock /アプリ名/Gemfile.lock

RUN gem install bundler
RUN bundle install
ADD . /アプリ名

アプリ名を自身の開発しているアプリ名に変えましょう。

Docker-compose.ymlを作成しましょう。

アプリ名 % touch docker-compose.yml

下記を記述しましょう。

docker-compose.yml
version: '3'
services:
  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: 'password' # このままpasswordとしても問題なく動く
    ports:
      - "4306:3306" #DockerコンテナとSequelpro接続の為に必要な設定

  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/アプリ名
    ports:
      - "3000:3000"
    depends_on:
      - db

config/database.ymlを編集

config/database.yml
default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: password
  socket: /tmp/mysql.sock
  host: db
development:
  <<: *default
  database: アプリ名_development


production.
test:
  <<: *default
  database: アプリ名_test

追加されたのは、passwordhost: dbのみ

docker-compose.yml buildでコンテナの作成

アプリ名 % docker-compose build

エラーがなかったら成功です。

コンテナ上でDB作成とmigrateの実行

アプリ名 % docker-compose run web bundle exec rails db:create

Rails6だとこのコマンドを実行するとエラーが出てしますので編集します。

config/webpacker.yml
  # Verifies that correct packages and versions are installed by inspecting package.json, yarn.lock, and node_modules
  check_yarn_integrity: false

およそ56行目あたりcheck_yarn_integrity: true
になっているのでこれをfalseに変えます。

編集が終わったら、もう一度同じコマンドを実行しましょう。
続いてmigrateしましょう。

アプリ名 % docker-compose run web bundle exec rake db:migrate

これでコンテナ上でdb設計ができました。最後にコンテナを起動しましょう。

アプリ名 % docker-compose up 

localhost:3000にアクセスし起動できていたら導入完了です。

docker hubから起動

複数のアプリをコンテナに積んだのでコマンドを打たずクリック一つでアプリを起動できます。
赤字のRANをクリックすると起動できます。
スクリーンショット 2021-01-14 13.27.21.png

もう一回クリックすれば停止できます。

単語集

①dockerfileって何

コンテナを作成する材料。docker-compose build のコマンドを実行するとステップに分けた読み込みをしていたと思います。読み込みが成功したらコンテナが作成されたよの意味。

②docker-composeって何

複数のコンテナを同時に動かすためのツールのこと

こんな感じです!
もっと詳しく書けるように頑張ります。

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

プロセスとスレッド、シングルプロセスとマルチプロセスの違い

Dockerの勉強を進めるにあたって、Docker Engineの仕組みを理解するには、プロセスの概念を理解する必要がありましたので、プロセスの詳細について調べてみました。

コンテナは、コンテナの作成、起動、削除を管理するDocker Daemonと同じく、ホストOS上でプロセスとしての存在になります。ホストOS上のプロセスということで、他のホストOS上で単独実行アプリケーションと同様に、CPU、メモリ、ネットワークなどのリソースをホストOS経由でアクセスできますし、また、プロセスが終了すると、メモリに保持されているコンテナ上の操作データも一緒に消えるが当然なことがよく理解できました。

■プロセスとスレッドの違いについて

1プログラム⇒1プロセス
1プロセスに複数のスレッドを動かすことが出来る(シングルスレッドとマルチスレッドがある)
スレッドがプロセス内の命令を実行する
1スレッドが1CPUコア使用する
1CPUに複数のCPUコアを含むことが出来る。

メモリー空間はプロセス単位で割り当てられる
スレッドが属するプロセスのメモリ空間を共有する

■シングルプロセスとマルチプロセスの違い
シングルプロセス:
 スレッド①:料理開始⇒ご飯を炊く⇒カレーを煮込む⇒お皿に盛る⇒料理終了
マルチプロセス:
 スレッド①:料理開始⇒プロセス②を起動⇒ご飯を炊く⇒プロセス②完了を待つ⇒料理終了
 スレッド②:カレーを炊く
 

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

Dockerの仕組みを理解するためのプロセスの概念を調べてみました

Dockerの勉強を進めるにあたって、Docker Engineの仕組みを理解するには、プロセスの概念を理解する必要がありましたので、プロセスの詳細について調べてみました。

コンテナは、コンテナの作成、起動、削除を管理するDocker Daemonと同じく、ホストOS上でプロセスとしての存在になります。ホストOS上のプロセスということで、他のホストOS上で単独実行アプリケーションと同様に、CPU、メモリ、ネットワークなどのリソースをホストOS経由でアクセスできますし、また、プロセスが終了すると、メモリに保持されているコンテナ上の操作データも一緒に消えるが当然なことがよく理解できました。

■プロセスとは
プロセスとは、HDDなどに格納されているバイナリーコードをOSのスケジューラーにより、メモリにロードされ、CPUを実行可能な状態となる、OS上でのCPUなどのリソース実行管理単位のこと。

■プロセスとスレッドの違いについて
1プログラム⇒1プロセス
1プロセスに複数のスレッドを動かすことが出来る(シングルスレッドとマルチスレッドがある)
スレッドがプロセス内の命令を実行する
1スレッドが1CPUコア使用する
1CPUに複数のCPUコアを含むことが出来る。

メモリー空間はプロセス単位で割り当てられる
スレッドが属するプロセスのメモリ空間を共有する

■シングルプロセスとマルチプロセスの違い
シングルプロセス:
 スレッド①:料理開始⇒ご飯を炊く⇒カレーを煮込む⇒お皿に盛る⇒料理終了
マルチプロセス:
 スレッド①:料理開始⇒プロセス②を起動⇒ご飯を炊く⇒プロセス②完了を待つ⇒料理終了
 スレッド②:カレーを炊く
 

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

【Docker Network 第1章】Dockerネットワーキングについて解説

image.png

はじめに

Dockerのエコシステムを理解するには、コンテナネットワーキングについての十分な知識が必要です。
これから3章にわたる記事を投稿しますが、この第1章では最も重要なコンテナネットワーキングの概念について説明します。ここで紹介するさまざまな概念を理解するには、Dockerの専門家である必要はありませんが、ネットワーク、Docker、およびKubernetesの基本的な知識が必要になるものかと思います。

Dockerは、コンテナー内で実行される分離された環境を作成、構築、実行するために設計されたツールです。アプリケーションをコンテナ化して軽量コンテナ内で実行できるようにするために広く使用されています。 Dockerをマスターするには、イメージの作成方法、実行方法、コンテナの保護方法、Dockerファイルシステムの操作方法、Dockerネットワークの管理方法に精通している必要があります。

そして、その中のDockerネットワーキングは、学習の過程で最も混乱する部分かもしれません。ここ数年の間に、このテクノロジーを中心にダイナミックなエコシステム全体が開発されました。 Docker Compose、Docker Swarm、Kubernetesなどのテクノロジーは、コンテナー化エコシステムの多くの問題を解決しましたが、特にネットワーキングに新しい課題をもたらしました。 Dockerエコシステムをよく理解するためには、ネットワーキングについての十分な知識が必要となってくるということです。

コンテナ:1つのことを実行し、うまく実行する

コンテナー(Wordpressなど)を実行すると、イメージを構築してWebサーバー(NginxまたはApache)+ PHPまたは(PHP FPM)+ Mysql / MariaDBデータベースを使用できます。
このソリューションは、多くのネットワークの問題を解消します。また、supervisordなどのプロセスマネージャーを使用して、プロセスが実行されていることを確認できます。

ただし、イメージにレイヤーを追加することになるので、これは良い方法ではありません。supervisordを使用するには、それをインストールし、その構成をコンテナーに同梱する必要があります。重要なプロセスとは、重要なプロセスとソフトウェアパッケージのみを含む軽量コンテナを構築して実行することです。

さらに、単一のコンテナで複数のプロセスを実行することは良くないパターンです。コンテナー内で独自のプロセスを実行することをお勧めします。

Wordpressの場合、Webサーバー(ApacheまたはNginx)用のコンテナー、PHP用のコンテナー、およびデータベース用の別のコンテナーが必要です。これらのコンテナーは相互に通信する必要があります。Webサーバーは要求を受信し、要求をPHPコンテナーに送信します。後者がデータを必要とする場合は、データベースコンテナーに要求します。逆の経路も方程式に取り入れなければなりません。これらのコンテナーを異なるホストで実行する場合、それらが同じホストにない場合でも、それらは互いにトラフィックを送受信できるはずです。複数のホスト間のトラフィックについては、最低限のセキュリティ標準を検討する必要があります。また、ウェブサーバーまたはアプリケーションコンテナーをスケーリングし、ロードバランサーを使用してそれらにトラフィックをルーティングする必要があるいくつかのケースに直面することもあります。

この使用例が基本的なように見えても、スタック全体を実行する上でネットワークがどのように重要な役割を果たすかがわかります。

オーケストレーション:複雑な層?

スタンドアロンコンテナを実行することは可能ですが、高可用性環境、特に本番環境では、これらのコンテナを管理するためにオーケストレーションプラットフォームが必要になります。

Kubernetesのようなオーケストレーションシステムを使用すると、コンテナだけでは満足のいく解決策を提供できない多くの問題が間違いなく解決されます。

それらのいくつかを識別しましょう:

  1. サービスを構成するコンテナーの数のスケールアップ/ダウン
  2. 同じサービスの異なるコンテナー間での負荷分散
  3. あるノード(VM)から別のノードへのコンテナーの転送
  4. 他のサービスおよびインターネットへのサービスの公開
  5. コンテナーとサービス間のサービス検出
  6. コンテナの配備

これらのユースケースと機能のほとんどを見ると、ネットワークが共通のポイントであることがわかります。

オーケストレーションは必須ですが、ネットワークの追加レイヤーも同時に追加されていきます。同じノード内のコンテナー間ネットワークの他に、マスターからクラスターへのネットワーク、クラスターからマスターへのネットワーク、インターネットからサービスへのネットワーク、サービスからポッドへのネットワーク、ポッドからポッドへのネットワーク、コンテナーからコンテナーへのネットワークなど、Kubernetesには複数のタイプのネットワークがあります。さらに詳しく説明したい場合は、ノード、kubelet、Kube-proxy、およびDNSネットワーキングも検討できます。

Kubernetesは最新のデータセンターオペレーティングシステムと見なされています。この大きさのプラットフォームでこのネットワークの複雑さを目にすると驚く人も多いでしょうが、Kubernetesで最も複雑でおそらく最も重要な部分の1つはネットワークです。ネットワーキングシステムを採用しない限り、Kubernetesを習得することはできません。

コンテナネットワークは複雑ですが難易度は高くありません

Zen of Pythonには次のような格言があります。

「Simple is better than complex. Complex is better than complicated.」

ITでは、Complexとは、システムのコンポーネントの数と、コンポーネント間の相互作用のレベルを指します。 一方,Complicatedとは、難易度が高いことを意味します。

特にオーケストレーションされたシステムでのコンテナーのネットワーキングはComplex(複雑)ですが、Complicated(難解)ではありません。 さらに、このComplexは、一般的な問題に対する抽象的なシステムと一般的なソリューションを作成するために必要な場合があります。 これは、Kubernetes開発者の1人であるJoe Bedaが宣言したものです

「KubernetesはComplexシステムです。これは多くのことを行い、エンジニアとして新しい抽象化をもたらします。私たちは自分で構築するComplexに対して、私たちが学ぶ必要があるComplicatedを無視する傾向があります。」

Bedaはさらに、Jenkins、Bash、Puppet / Chef / Salt / Ansible、AWS、Terraformなどを使用して複雑なデプロイメントシステムを作成すると、独自のComplexのブランドに慣れてしまうと言いました。それは有機的に成長したのでそれは複雑に感じませんが、このような有機的に成長したシステムで新しい人々を助けることは困難です。彼らはいくつかのツールを知っているかもしれませんが、それらを組み立てる方法は独特です。

ここは、Kubernetesが付加価値を提供する場所です。一般的な一連の問題を解決する一連の抽象化を提供します。人々がこれらの問題について理解とスキルを構築するにつれて、より多くの状況でより生産的になります。

コンテナーのネットワーキングは一見Complicatedですが、ネットワーキングに関する基本的な知識と新しいスキルの学習に投資する時間がある場合は、近づきやすいでしょう。

この次の章の記事では、技術的な詳細について詳しく説明します。スタンドアロンモードで実行した場合のDockerコンテナネットワークの仕組み、マルチコンテナネットワークの仕組み、スタンドアロンコンテナネットワークの違い、マルチコンテナネットワークについて理解します。また、複数のホストと魅力的なKubernetesネットワーキングの世界でネットワーキングを管理する方法についても説明します。

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

GCP上でGPUコンテナを構築してみる。

はじめに

GPUコンテナの作成を試したかったのだが、そのためにGPUを買う選択肢はなかったので、クラウド上でGPUインスタンスを作成して、そこでGPUコンテナを構築してみた。
以外に時間を要したので、自分用のメモとして手順やコマンドをまとめておく。

事前準備

・Google Cloudのアカウントを作成してGCPコンソールの画面に入れる状態にしておく。
・アップグレードする。(無料トライアルの状態だと、GPUの割当申請ができない)

環境

【ホストOS】
 ・Ubuntu 20.04 LTS(GCP上)
 ・Nvidia-driver 460.
 ・docker 19.03.14
 ・Nvidia-driver2 2.5.0

GPUコンテナの作成手順

1.GPUインスタンスの作成
2.ホストの設定
3.GPUコンテナの作成

1.GPUインスタンスの作成

GPUの割当申請をする

GPUを搭載したVMインスタンスを作成する場合、初回のみ割り当て(クオータ)申請が必要。
まずはGCPのコンソールからIAMと管理 > 割り当てを選択する。、
申請は2つする必要があり、【全体における割り当て数】と、【各GPUのリージョン毎の割り当て数】の申請が必要。

【全体における割り当て数】
フィルタにGPUsと入れて、下図のサービスを選択する。

Qiita-no024_img04.jpg

グローバルにチェックを入れて、『割り当て編集』をクリック。上限と理由を記入して次へ進む。

Qiita-no024_img05.jpg

次の画面で、【名前】、【メールアドレス】、【電話番号】を入力してリクエストを送信する。
5分程で承認が下りるため、次はGPUインスタンスを作成する。

【各GPUのリージョン毎の割り当て数】

適当にフィルタをかけて、今回はNVIDIA T4を選ぶ。
 ※利用料金の詳細はこちらを参考に ⇒ https://cloud.google.com/compute/gpus-pricing?hl=ja

Qiita-no024_img01.jpg

Qiita-no024_img02.jpg

割り当てはリージョン単位になるため、GPUインスタンスを立てる予定のリージョンを選択し、次にGPU数の上限を指定する。
ここで指定した数値は上限値なので、この時点で課金が発生することはない。今回はGPUコンテナの構築が目的のため1個。

Qiita-no024_img03.jpg

GPUインタスタンスの作成

GCPのコンソールからCompute Engine > VMインスタンスを選択。
[作成] をクリックし、以下のスペックで作成。

 <右側は今回の設定値>
 ●リージョン:us-central1(アイオワ)
 ●ゾーン  :us-central1-a

 ●マシン構成
   マシンファミリー:GPU
   シリーズ    :N1
   マシンタイプ  :n1-standard-1(1vCPU、3.75GBメモリ)
  ※試しに申請したリージョン以外を選択すると、GPUのタグは出てこない。
 
 ●GPUのタイプ
   GPUのタイプ:NVIDIA Tesla T4
   GPUの数  :1
 
 ●ブートディスク
   OS      :Ubuntu
   バージョン  :Ubuntu 20.04 LTS
   ディスクの種類:標準の永続ディスク
   サイズ    :20GB

 ●ファイアウォール
   HTTPトラフィックを許可
   HTTPSトラフィックを許可

起動に数分かかった。。。

サーバー環境の確認

OSの確認
$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=20.04
DISTRIB_CODENAME=focal
DISTRIB_DESCRIPTION="Ubuntu 20.04.1 LTS"
GPU(NVIDIA製)の確認
$ lspci -vv | grep -i nvidia
00:04.0 3D controller: NVIDIA Corporation TU104GL [Tesla T4] (rev a1)
        Subsystem: NVIDIA Corporation TU104GL [Tesla T4]
        Kernel modules: nvidiafb

2.ホストの設定

nouveauグラフィックスドライバの無効化
 linuxにデフォルトで入っているnouveauグラフィックスドライバというのを無効化する必要があるらしい。

$ lsmod | grep -i nouveau

 ※今回のVM環境は入っていなかったため、特に何も返ってこなかった。

パッケージ管理ツールのアップデート

$ sudo apt update
$ sudo apt upgrade

Nvidiaドライバーのインストール

 NVIDIAのDriverバージョンは、こちらのサイトより確認できる。https://www.nvidia.co.jp/Download/index.aspx?lang=jp  

リポジトリを追加してアップデート

$ sudo add-apt-repository ppa:graphics-drivers/ppa
$ sudo apt update

インストール推奨Driverを確認

$ sudo apt ubuntu-drivers-common
$ ubuntu-drivers devices
== /sys/devices/pci0000:00/0000:00:04.0 ==
modalias : pci:v000010DEd00001EB8sv000010DEsd000012A2bc03sc02i00
vendor   : NVIDIA Corporation
model    : TU104GL [Tesla T4]
driver   : nvidia-driver-418-server - distro non-free
driver   : nvidia-driver-460 - distro non-free recommended
driver   : nvidia-driver-440-server - distro non-free
driver   : nvidia-driver-450 - distro non-free
driver   : nvidia-driver-450-server - distro non-free
driver   : xserver-xorg-video-nouveau - distro free builtin

ドライバーのインストール

$ sudo apt install nvidia-driver-460

再起動をして問題なくインストールされたか確認

GPU(NVIDIA製)の確認
$ lspci -vv | grep -i nvidia
00:04.0 3D controller: NVIDIA Corporation TU104GL [Tesla T4] (rev a1)
        Subsystem: NVIDIA Corporation TU104GL [Tesla T4]
        Kernel driver in use: nvidia
        Kernel modules: nvidiafb, nvidia_drm, nvidia

 ※ドライバー情報が追加されていればOK。

nvidia-smiコマンドの動作確認
$ nvidia-smi

dockerのインストール

 【Dockerコンテナ内のUbuntuではsystemctlは使えない】の手順1を参考に。
 ※dockerバージョンはdocker-ce=5:19.03.14~3-0~ubuntu-focalとする

nvidia-docker2をインストール

 GPUコンテナを作成・起動するために必要なパッケージをインストール。

リポジトリを追加してアップデート
 https://nvidia.github.io/nvidia-docker

# GPG鍵の登録
$ curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -

# リポジトリを追加
$ distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
$ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list

$ sudo apt update

nvidia-docker2のインストール

インストール可能なパッケージバージョンを確認
$ apt-cache madison nvidia-docker2
# 最新版のインストール(今回はこちらを実行)
$ sudo apt -y install nvidia-docker2

# バージョン指定をしてインストールする場合はこんな感じ
$ sudo apt -y install nvidia-docker2=2.0.3+docker18.09.7-3

# 古いバージョンだと事前に他のパッケージもインストールが必要となる場合がある。(以下参考)
$ sudo apt install nvidia-container-runtime-hook
$ sudo apt install nvidia-container-runtime=2.0.0+docker18.09.7-3

 ※現在はnvidia-docker2をインストールすると、nvidia-container-toolkitも依存関係があり一緒にインストールされる。(nvidia-container-toolkitの方が新しいパッケージ。)
nvidia-container-toolkitパッケージのみをインストールした場合は、DockerがGPU にネイティブ対応したため、--runtime=nvidianvidia-dockerコマンドは使えない。

dockerのデーモン設定をリロード

$ sudo pkill -SIGHUP dockerd
$ sudo nvidia-docker version
NVIDIA Docker: 2.5.0
Client: Docker Engine - Community
 Version:           20.10.2
 API version:       1.40
 Go version:        go1.13.15
 Git commit:        2291f61
 Built:             Mon Dec 28 16:17:43 2020
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          19.03.14
・・・・
・・・・

3.GPUコンテナの作成

GPUコンテナのイメージ取得

  詳細はこちら https://hub.docker.com/r/nvidia/cuda/

$ docker image pull nvidia/cuda:11.1-base-ubuntu20.04

GPUコンテナの起動確認

最新コマンド(docker19.03以降でサポートされた`--gpus`オプションを使う場合)
# 全てのGPUを使用する場合
$ docker container run --gpus all --rm nvidia/cuda nvidia-smi

# 使用するGPUを指定したい場合
$ docker container run --gpus '"device=0,1"'--rm nvidia/cuda nvidia-smi

 ※nvidia-docker2のバージョンが新し過ぎたせいか、devicesなどのオプション(環境変数?)の設定が足りてなくてnvidia-smi実行ができなかった。

旧コマンド(docker19.03以前+nvidia-docker2パッケージが入っている場合)
$ docker container run --runtime=nvidia --rm nvidia/cuda:11.1-base-ubuntu20.04 nvidia-smi
# or
$ nvidia-docker run --rm nvidia/cuda:11.1-base-ubuntu20.04 nvidia-smi

# 使用するGPUを指定したい場合
$ docker container run --runtime=nvidia NVIDIA_VISIBLE_DEVICES=0,1 --rm nvidia/cuda:11.1-base-ubuntu20.04 nvidia-smi
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む