GPU対応のDockerコンテナ作成

サーバ開発で当たり前のように使われるコンテナ技術(Docker等)ですが、GPUが絡んでくると最初の設定でつまづくことが多々あります。ここでは、こうやったらできたというのをメモとして残しておきたいと思います。

ホスト側のGPU設定

コンテナを作る前に、そのコンテナが動くホストのGPUが使える状態になっていないと、当然コンテナでも使えません。なので、まず初めにホスト側のGPUが使えるかの確認です。ホストOSはubuntuを前提に書きます。

GPUが使えるかどうかは、nvidia-smiコマンドで確認できます。これで、GPUの使用率などが表示されたら使える状態です。nvidia-smiコマンドが見つからない場合は、/usr/local/cuda等を探してみましょう。それでも入ってなさそうな場合は、cudaをインストールする必要があります。

CUDAのインストールは、ubuntu20.04の場合、

wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/cuda-keyring_1.1-1_all.deb
sudo dpkg -i cuda-keyring_1.1-1_all.deb
sudo apt-get update
sudo apt-get -y install cuda

と、1行ずつ実行すればインストールできます。

nvidia-smiコマンドもインストールされていると思います。nvidia-smiコマンドでGPUの情報が見られればOKです。

AWSのGPUインスタンスを使う場合は、AWSから提供されているDeepLearning Base AMI (ubuntu20.04)を使うと楽です。

GPUのDockerコンテナ作成

GPU対応のDockerコンテナを作成する場合、元となるイメージも普通のubuntuイメージではなく、nvidia/cudaのイメージを使う必要があります。

こちらのDocker Hubで、nvidia/cudaのイメージリストがありますので、この中から選んで docker pullすることでイメージをダウンロードでき、イメージからコンテナを作成できます。

作成したコンテナの中に入り、GPUが使えるように設定していきます。

まず、NVIDIA Container Toolkitをインストールします。

これはLinuxのDistributionごとにURLが変わるので、まずコンテナ内のLinuxのDistributionを見なければいけないです。

$ cat /etc/os-release

とすれば、OS情報が見れます。この中のIDとVERSION_IDをくっつけたものがDistribution名になります。

bashであれば、下記のコマンドで distributionという変数にDistribution名を格納できます。

$ distribution=$(. /etc/os-release;echo $ID$VERSION_ID)

そしてこの distribution変数を使って、curlでapt用のパッケージリストをとってきます。

$ curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add - 
$ 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 && sudo apt install -y nvidia-container-toolkit 

これで、dockerコンテナ起動時に、–-gpus all オプションをつければ、コンテナ内でGPUが利用できるようになっています。

$ docker run -it -d --gpus all --name [container_name] docker_image_name:tag
$ docker exec -it [container_name] sh

コンテナ内で nvidia-smiコマンドを実行して、GPU情報がでてくれば大丈夫です。

docker-composeでGPUコンテナを起動

docker-composeでコンテナを作成する場合は、–-gpusオプションと同等のオプションが無いため、もう少しやることがあります。

まず、nvidia-container-runtimeをインストールします。

$ sudo apt install nvidia-container-runtime

設定ファイルを /etc/docker/daemon.jsonに作成します。

{ "runtimes": 
  { "nvidia": 
    { "path": "nvidia-container-runtime", 
      "runtimeArgs": [] 
    } 
  } 
}

これで、docker-composeの設定ファイルで runtime: nvidia ができるようになります。

docker-compose.ymlの例を記載します。

version: '2.3'
services:
  [service_name]:
    image: [image_name]:[tag_name]
    container_name: [container_name]
    runtime: nvidia
    environment:
      - NVIDIA_VISIBLE_DEVICES=all
    tty: true
    ports:
      - 80:80
      - 443:443
    volumes:
    - /var/host:/var/docker

このdocker-compose.ymlファイルがある場所で、docker-compose up -d でコンテナを立ち上げて、コンテナ内で nvidia-smiを実行し、GPU情報が見れればコンテナ内でもGPUが使えます。

おまけ(コンテナ内の環境設定)

作りたてのコンテナでは、GPU以外にもいろいろとインストール・設定することがあると思います。これもメモですが、だいたいこのあたりは使うだろうというものを書いておきます。

コンテナ内がubuntuの例で書きます。

$ apt-get update

これはすでに上記のGPU設定でやってますが、一応書きます。これでいろいろ必要なものをインストールできるようになります。

あと、gccとかmakeとかも入ってないのでこのあたりの開発コマンドを入れます。

$ apt update 
$ apt install build-essential

pythonも使うなら、

$ apt-get install python3-distutils 
$ apt-get install python3-dev

pipのインストールは

$ apt-get install wget 
$ wget https://bootstrap.pypa.io/get-pip.py 
$ python3 get-pip.py

ここまでやれば、AWSでubuntuのEC2インスタンスを立ち上げたぐらいの状態になってると思います。

ただひとつ困ったことがありました。dockerのシェル上で、Ctrl-pが使えないのです。(dockerのdetachのコマンドのため) Ctrl-pは、ひとつ前のコマンドを実行したいときに多用するので、これが使えないと困ります。一応2回押せばできるんですが、そんなのは無理です。 上矢印キーでもできるんですが、手をホームポジションから動かすのは嫌です。

ですので、Ctrl-pを使えるようにします。

~/.docker/config.json の設定ファイルの中に

"detachKeys": "ctrl-\\"

と書いて、detach key をCtrl-pとは違うキーに割り当てます。これで、Ctrl-pが使えるようになります。

これでubuntuで遊べるようになりました。せっかくなので、この状態をイメージに保存しておきたいと思います。イメージとして保存しておけば、この状態からコンテナを作成できるようになります。

$ docker commit [container_name] [image_name]:[tag_name]

これで、このコンテナが、[image_name]で保存されて、[tag_name]というタグが付いています。

WordPressのインストール

ブログを始めようと思った時に、アメブロやFC2ブログなど、無料でお手軽に始められるブログサービスがたくさんありますが、やっぱり独自の城を築きたいと思う方にはWordPressがおすすめです。環境構築など、少しのITリテラシーと少しのサーバ費用が必要ですが、SEO対策などが施されており上位表示されやすく、ドメインも独自ドメインにできるためかっこがつきます。

ここではWordPressの導入をわかりやすく説明していきたいと思います。

WordPressの前提知識

WordPressを導入するためには、レンタルサーバやAWS等を利用して自分のサーバを持つ必要があります。月に数百円程度の出費でブログには十分な自分専用のサーバが利用できるようになります。ここでは、そのサーバでWordPressがどう動くのかを説明します。

まず、WordPressをダウンロードしてみましょう。こちらの公式サイトからダウンロードできます。

ダウンロードしたzipファイルを解凍すると、wordpressというフォルダができて、その下にフォルダやファイルがたくさんあります。

それでは、全体像を説明します。

WordPressのインストール概要

まず、ダウンロードしたwordpressのファイル達をWebサーバにアップロードする必要があります。Webサーバのどこに置けばよいかというと、ブラウザからWebサーバにアクセスした時に見えるドキュメントルートというフォルダに置く必要があります。レンタルサーバの多くの場合、wwwというフォルダです。自分でApacheなどのWebサーバを導入した場合は、/var/www/htmlがデフォルトだと思います。

とにかくここに、先程ダウンロードしたwordpressのファイル達をごっそりコピーすれば良いです。(レンタルサーバによって様々ですが、FTP、SCP、ファイルマネージャーなどを駆使してコピーします)

このWebサーバ以外に、データベースというものを把握しておく必要があります。これはブログの記事やコメントなどを保存しておく場所です。レンタルサーバではたいていデータベースもセットで提供してくれるので、あまり気にする必要はありませんが、後ででてくるWordPressの設定でデータベースの設定も必要になってくるので、把握しておいた方が良いです。

データベースもひとつのサーバとして動いています。なのでサーバのホスト名なるものが存在します。その中にデータベースというものを複数作れます。WordPress用にひとつのデータベースを使います。このデータベースにも名前があり、データベース名と言います。

さらにデータベースの中にテーブルというものが複数作成されます。こちらはWordPressが自動的に作ってくれるので気にする必要は全くありませんが、ここに固定ページ用のテーブルや投稿ページ用のテーブルなどがあり、保存されていきます。

データベースサーバには、ユーザ名とパスワードでアクセスできるようになっているので、このデータベースサーバにアクセスできるユーザ名とパスワードがWordPressの設定に必要になってきます。

まとめると、以下の情報がWordPressの設定に必要になってきます。

  • データベースのホスト名
  • データベース名
  • データベースにアクセスできるユーザ名とパスワード

これらはレンタルサーバの場合、最初から提供されていたりします。

一番つまづきそうな点は、やはりWordPressのサーバへのインストールなのですが、これもレンタルサーバによっては自動でできる場合があります。

さくらインターネットの場合は、コントロールパネルでこんな感じのものがあり、WordPressのインストールもボタンひとつでできてしまいます。

今までの説明はなんだったのかと思うかもしれませんが、たとえボタンぽちっでインストールできたとしても上記の概念的なことはわかっておいて損はないと思います。

WordPressの設定

つぎに、いよいよWordPressの設定なのですが、これは先程のWebサーバにブラウザから普通にアクセスすれば始まるようになっています。

どこにアクセスすればよいかというと、それはWebサーバのドメイン名で、

http://Webサーバのドメイン名/

にアクセスすれば良いです。Webサーバのドメイン名ですが、デフォルトだとレンタルサーバが提供するサーバ名(ドメイン)がついてると思います。

でも、せっかくなのでブログの内容がわかるような独自ドメインをつけたいですね。それについてはまた別記事で触れたいと思います。ひとまず、WordPressの設定を続けます。

このような画面がでてきたら、WordPressが正常にインストールされていて動いています。この後、データベースの設定をしていきます。「さあ、始めましょう!」ボタンを押しましょう。

ここに先ほど説明したデータベースの各種情報を入力していきます。最後のテーブル接頭辞はWordPressがテーブルを作る際の命名規則になりますが、複数のサイトを同じデータベースで運用しない限りはこれを変える必要はありません。そのままにして「送信」ボタンを押しましょう。

このような画面がでてきたら、入力したデータが正しく設定されてデータベースにも接続できております。「インストール実行」を押しましょう。

サイトの内容を設定していきます。タイトルはブログのタイトルですね。ユーザ名とパスワードは、サイトの編集モードにログインするためのユーザ名・パスワードになります。メールアドレスは、当然ですが自分が読めるメールアドレスを入れましょう。そして「WordPressをインストール」を押します。

この後、WordPressが自動的にテーブルなどを作成して完了します。

完了したらログイン画面がでてくると思いますので、上記で設定したユーザ名・パスワードでログインしましょう。WordPressのダッシュボードがでてきたら、WordPressライフの始まりです。

おすすめのプラグイン

WordPressには便利なプラグインがたくさんあり、自分好みのプラグインをインストールして機能を好きに拡張していけます。その中でも必須と思われる機能として、バックアップとSEO対策の2つをご紹介します。

どちらも All-in-One XXX という名前なので、プラグイン追加画面で、All in Oneで検索すれば両方でてきます。

バックアップの方は右側の、All-in-One WP Migrationというプラグインで、サイト全体のデータをエクスポートして、zipファイルとして保存できます。復元はこのzipファイルをインポートするだけです。とても簡単にバックアップができます。

SEO対策の方は左側の、All in One SEO というプラグインで、SEO対策の定番となっております。サイトマップの作成から、SEO観点で記事の良し悪しやサイト全体を採点してくれたりするので、SEO的に良い記事や良いサイトを作りやすいです。

他にも目次を作ってくれるプラグインなど便利なものがたくさんありますので、バックアップをとりながらいろんな機能を試してみるのも良いと思います。

PHPのライブラリ管理ツール Composer をインストール

Composerとは、PHPのライブラリを容易にインストールしてくれるツールで、ライブラリの依存関係も自動的に判断して必要なライブラリも自動的にインストールしてくれる便利なツールです。

PHPでWebアプリを実装する場合、JWTトークンの検証や決済プロバイダのSDKなど、さまざまなライブラリがあります。ここでは、それらをインストールして使えるようにする方法を紹介します。

Composerのインストール

では早速Composerのインストールですが、Composerの公式サイトにダウンロード・インストール方法が記載されているので、そのまま行うだけです。ですが、英語で書かれているので、日本語にしながら転載します。(Macならbrew install composerでもインストール可能です)

php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('sha384', 'composer-setup.php') === 'dac665fdc30fdd8ec78b38b9800061b4150413ff2e3b6f88543c636f7cd84f6db9189d43a81e5503cda447da73c7e5b6') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"

この4行を1行ずつ実行するだけです。PHPがインストールされていてコマンドで実行できる必要があります。

実行した場所に、composer.phar という実行ファイルができていると思います。これが管理ツールのコマンドとなります。試しに実行してみましょう。

./composer.phar

Composerのテキストロゴ、バージョン、オプションの説明が表示されたらOKです。

このコマンドをどこでも利用できるように /usr/local/bin などにコピーしましょう。名前もpharを取ってcomposerにしましょう。

sudo mv composer.phar /usr/local/bin/composer

これでどこでもcomposerが使えるようになりました。

ライブラリのインストール

次にcomposerを使って、PHPのライブラリをインストールする方法です。実行した場所にvendorというフォルダができて、この下にライブラリが保存されます。PHPファイルから読み込みやすいように、PHPファイルを置く場所で実行すると良いです。

たとえば、認証等で使うJWTトークンを検証するためのライブラリをインストールする場合は、

composer require firebase/php-jwt
composer require codercat/jwk-to-pem

を1行ずつ実行します。vendor/firebaseやvender/codercatというフォルダができてここにインストールされています。

もうひとつ、クレジットカード決済を行う決済プロバイダ StripeのSDKをインストールする場合は、

composer require stripe/stripe-php

を実行します。verdor/stripeというフォルダにインストールされます。

vendor/autoload.phpというファイルがありますが、プログラムからはこれを読み込むだけでライブラリを使えるようになります。

ライブラリの使用

では、PHPプログラムからライブラリをどう使うかですが、これも簡単で冒頭に2~3行書くだけです。

例えば、php-jwtを使う場合は、

<?php
  require __DIR__ . '/vendor/autoload.php';
  use Firebase\JWT\JWT;
  use CoderCat\JWKToPEM\JWKConverter;

と書きます。requireでライブラリのある場所を指定し、useでJWTのライブラリを使うことを宣言しています。この後、JWT::encode() や JWT::decode() などのように関数を利用できます。

もうひとつ、StripeのSDKを利用する場合は、

<?php
  require __DIR__ . '/vendor/autoload.php';
  \Stripe\Stripe::setApiKey($secret_key);

のようにuseを使わずにライブラリを使うことも可能です。useは名前空間に別名をつけるだけですので、フルパスで指定すれば直接使えます。この例では、StripeのAPIキーを設定しています。($secret_keyはシークレットキーです)

(おすすめのライブラリ).envファイルを使いましょう

シークレット情報や環境設定情報などを別のファイルに分けておきたい場合に便利なのが .envファイルです。こちらもcomposerでライブラリをインストールすれば使えます。

composer require vlucas/phpdotenv

これで、vender/vlucasにphpdotenvがインストールされて使えるようになります。使い方は上記と同様に、

<?php
  require __DIR__ . '/vendor/autoload.php';
  Dotenv\Dotenv::createImmutable(__DIR__)->load();

で利用できて、同フォルダの.envファイルを読み込めます。.envの書き方は、

SECRET_KEY="secret"
PUBLIC_KEY="public"

のような書き方で、PHPファイルの中で$_ENVの連想配列として参照できます。

<?php
  require __DIR__ . '/vendor/autoload.php';
  Dotenv\Dotenv::createImmutable(__DIR__)->load();

  $secret_key = $_ENV['SECRET_KEY']
  $public_key = $_ENV['PUBLIC_KEY']

気をつけたいのは、.envファイルにはAPIキーやパスワードを書いたりするため、公開してはいけません。公開github等にpushしてしまわないように、.gitignoreで除外する等しましょう。

また、Webサーバにデプロイした場合にも、.envを直接参照できてしまうと情報がダダ漏れになってしまいますので、.envファイルはWebサーバからアクセスできないところに置く方が賢明です。

.envを別の場所に置いた場合は、上記の __DIR__ 部分を書き換えて、.envを置いたフォルダパスを書けば読み込めます。