1. dockerとは
ネイティブな環境とほとんど変わらない高速な動作が可能な仮想環境を作れる、CPUコア数やメモリ容量を指定した複数の仮想環境を同時に起動できる、imageファイルを切り替えることで即座に環境構築ができる、などの素晴らしい機能によりデファクトスタンダードとなった仮想環境ツールです。
docker公式ページ
https://docs.docker.com/
2. インストール
2-1. Windows環境でのインストール
docker desktopのインストール
ダウンロードしてきてインストーラーします
https://www.docker.com/products/docker-desktop
Windows版のdockerはWSL2を利用しますので、この時点で起動してもエラーが出ます
https://docs.microsoft.com/ja-jp/windows/wsl/install-win10
上記を解決する為に以下の手順をやっていきます
WSL2をdockerが使えるようにする
Windows版のdockerはWSL2を利用しますのでこれを使えるようにしてやります
https://docs.microsoft.com/ja-jp/windows/wsl/install-win10
WSLを有効にする
Windowsの設定内になる「Windowsの機能の有効化または無効化」を開きます
(設定の検索窓から探すと早いと思います)
「Linux用Windowsサブシステム」と「仮想マシンプラットフォーム」にチェックを入れます。
カーネル更新プログラムパッケージを適用する
2021年4月29日現在ではx64 マシン用 WSL2 Linux カーネル更新プログラム パッケージをダウンロードしてきて実行すれば適用されます。
Docker Desktopを起動して以下のように表示されたら正常です
Windows版でCLIkらdockerを使う場合、一度Docker Desktopを起動しておく必要があるようです。
docker: error during connect: This error may indicate that the docker daemon is not running.: Post http://%2F%2F.%2Fpipe%2Fdocker_engine/v1.24/containers/create: open //./pipe/docker_engine: The system cannot find the file specified.
See 'docker run --help'.
2-2. Linux環境でのインストール
Ubuntu18.04でやってみます
アップデートします
sudo apt update
aptがHTTPS経由でリポジトリを使用できるようにパッケージをインストールする
sudo apt install \
apt-transport-https \
ca-certificates \
curl \
gnupg-agent \
software-properties-common
dockerの公式GPG公開鍵を追加
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
公開鍵のフィンがプリントを確認
sudo apt-key fingerprint 0EBFCD88
リポジトリを設定します
x86_64の場合はarch=amd64です
sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"
もう一度アップデートしてdockerをインストールします。docker-ce=以下にバージョンを入力して指定できますが、省略した場合は最新版がインストールされます。
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io
最後にdockerのバージョンを確認しておきましょう
$ sudo docker version
Client: Docker Engine - Community
Version: 20.10.6
API version: 1.41
Go version: go1.13.15
Git commit: 370c289
Built: Fri Apr 9 22:46:01 2021
OS/Arch: linux/amd64
Context: default
Experimental: true
3. CLIで使う
3-1. コンテナの生成/起動する
docker runコマンドでコンテナの生成と起動が実行されます。
localに当該dockerイメージがない場合はdocker hubから自動的にダウンロードしてきてくれます。docker pullコマンドでダウンロードのみ行うことも出来ますが、その後docker runするのは同じです。
docker run hello-world
上記を実行すると以下のようにhello-worldコンテナが実行された結果が表示されます
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/get-started/
ここで生成済みコンテナ一覧を表示してみましょう
> docker container ls --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f28a2890b770 hello-world "/hello" 1 minutes ago Exited (0) 1 minutes ago frosty_keller
hello-worldイメージにfrosty_kellerというNAMEをつけて生成されているのが分かります。この名前はdockerがランダムに割り当てるもので、同じコンテナが複数起動しているときに見分けが付くようにしてくれているものです。
https://docs.docker.jp/engine/reference/run.html#name
3-2. NAMEを指定する
docker runする際にNAMEを指定することが出来ます
docker run --name "hello-world-01" hello-world
同様にコンテナ一覧を出すと、今度はhello-world-01というNAMEでコンテナが実行されたことが分かります。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8caa8b8325f9 hello-world "/hello" 5 seconds ago Exited (0) 4 seconds ago hello-world-01
f28a2890b770 hello-world "/hello" 4 minutes ago Exited (0) 31 minutes ago frosty_keller
3-3. 結果をコンソールに出力する
-itオプションによりコンテナの出力をterminalに表示してみます
docker run -it lukaszlach/merry-christmas
-itオプションはstdinを有効にする-iオプションと擬似端末を有効にする-tオプションを同時に指示するものです。これによりdockerコンテナとCLIでやりとり出来るようになります。ctrl + c でコンテナを停止してCLIに戻れます。
3-4. デタッチドモードで実行する
dockerを通常起動するとCLIがコンテナの標準出力を受け付ける為に待機状態になりますが、-dオプションでデタッチドモードにすることでCLIが待機しないままバックグラウンドで起動することが出来ます。
https://docs.docker.jp/engine/reference/run.html#detached-vs-foreground
docker run -d lukaszlach/merry-christmas
ここで起動中のdockerコンテナを確認してみましょう。docker container lsと--allオプションを付けなければ起動中のコンテナのみを表示します。
>docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
17d7dedd1195 lukaszlach/merry-christmas "/tree /tree.txt" 20 seconds ago Up 19 seconds condescending_johnson
先程起動したコンテナが動いているのが分かります
3-5. コンテナを停止する
NAMEまたはUUIDを指定して停止できます。
> docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
17d7dedd1195 lukaszlach/merry-christmas "/tree /tree.txt" 25 minutes ago Up 40 seconds condescending_johnson
上記のようなコンテナを停止したい場合は以下のようにして停止できます。
docker stop 17d7dedd1195
docker stop condescending_johnson
3-6. 生成済みのコンテナを起動する
docker stopで停止したコンテナを再度起動することが出来ます
> docker start condescending_johnson
dockerコンテナのCLIにアクセスしたい場合は-aオプションを付けます
> docker start -a condescending_johnson
3-7. 生成済みのコンテナを削除する
要らなくなったコンテナはdocker rmコマンドで削除できます。
削除対象はUUIDまたはNAMEで指定します。
docker rm condescending_johnson
使っていないコンテナをまとめて削除することも出来ます
docker container prune
使った後にいちいち消すのが面倒な場合は実行時に-rmオプションを付けて終了時にコンテナを削除するように出来ます
docker run --rm (image名)
3-8. docker image一覧を表示する
> docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
alpine/git latest c99c7d810bc1 10 days ago 25.1MB
hello-world latest d1165f221234 8 weeks ago 13.3kB
centos latest 300e315adb2f 4 months ago 209MB
lukaszlach/merry-christmas latest bd797b67c25d 16 months ago 2.65MB
3-9. docker imageを削除する
docker rmiの引数にREPOSITORYまたはIMAGE IDを指定して削除します
docker rmi alpine/git
docker rmi c99c7d810bc1
起動していないimageをまとめて削除することも出来ます
docker image prune --all
3-10. CPU配分、メモリ上限を指定する
デフォルトではCPUとメモリは無制限になります
https://docs.docker.jp/config/container/resource_constraints.html
CPU
docker run --cpus=1.5 centos
docker run --cpu-shares=512 centos
メモリ
--memoryでメモリ使用量上限、--memory-swapでメモリスワップの上限+メモリ使用量上限を指定します
docker run --memory=512m --memory-swap=1g centos
--memory-swapを省略すると-memoryの値をスワップ上限に使います。
つまり上記の場合は--memory-swapを省略しても同じになります。
docker run --memory=512m centos
3-11. ポートに静的サイトを待機する
Nginxで静的サイトを待機してくれるimageを使ってポート操作を練習してみましょう。prakhar1989/static-site を起動すると80番ポート (html) に静的サイトが待機してくれますが、dockerを起動しただけではコンテナのポートとホストのポートが繋がらないのでサイトが開けません。なので-Pオプションまたは-pオプションでコンテナのポートをホストのポートに割り当ててやります。
ポートをランダムに割り当てる
-Pオプションをつけるとランダムなポートにサイトを割り当てられます
> docker run -d -P --name static-site prakhar1989/static-site
> docker port static-site
443/tcp -> 0.0.0.0:49153
80/tcp -> 0.0.0.0:49154
docker portでcontainerを指定するとポートの割当が見られます。上記の場合、80/tcpがhttpポートですので上記の場合は http://localhost:49154/ を開けばサイトが見られる筈です。
ポート番号を指定して割り当てる
-pオプションを使って、-p ホスト側のポート:コンテナ側のポートと指定したポートを繋げることが出来ます。以下のようにするとコンテナの80番ポートがホストの8080番ポートに繋がります。
> docker run -d -p 8080:80 --name static-site prakhar1989/static-site
以下を開くと画面が開きます
http://localhost:8080/
3-12. ホストとコンテナでファイルをやりとりする
docker cpコマンド
https://docs.docker.jp/engine/reference/commandline/cp.html
コンテナからホストにコピーする
「docker cp コンテナPATH ホストPATH」でコンテナの指定PATHからホストの指定PATHへのコピーが実行されます。PATHで指定する対象はフォルダでもファイルでも構いません。hoge名のコンテナの/home/pictures/フォルダからホストのpictures/フォルダにコピーする場合は以下のようになります。
docker cp hoge:/home/pictures/ pictures/
ホストからコンテナにコピーする
上記の逆にしてやれば同じようにホストからコンテナにコピーしてくれます
docker cp pictures/ hoge:/home/pictures/
3-13. imageを探す
dockerがimageファイルの共有用にdocker hubというページを用意してくれています。Ubuntu、centos、django、nodejsなどのdocker公式リポジトリと、各ユーザーが作った公開リポジトリを利用することが出来ます。
https://hub.docker.com/search?type=image
試しにgolang公式のimageを使ってみます
https://hub.docker.com/_/golang
docker pull golang
docker run golang
3-14. imageを作る
既にあるimageをベースにライブラリなどを追加して自分のimageを作ることが出来ます。
Dockerfileをつくる
まず、新規imageをつくる条件を書いたテキストファイルをつくりファイル名「Dockerfile」で保存します。FROMがベースとなるイメージ、RUNがimage作成時に実行するコマンド、EXPOSEがポート番号でCMDがコンテナ起動時に実行するコマンドになりますので、以下の場合はUbuntu18.04の公式imageにminicondaをインストールしてjupyter notebookを起動待機するimageをつくるDockerfileになります。
なお、&& \で繋げてるコマンドが途中で処理を失敗したときにどこまで進んだか分からないと困るので、set -xを入れて実行したコマンドそのものを標準エラー出力に出すようにしておきましょう。
FROM continuumio/miniconda3
# conda create
RUN conda create -n chemodel python==3.7
# install conda package
SHELL ["conda", "run", "-n", "chemodel", "/bin/bash", "-c"]
RUN conda install django=3.* -c conda-forge --override-channels
RUN conda install pytorch==1.7.1 torchvision==0.8.2 torchaudio==0.7.2 cpuonly -c pytorch -c conda-forge -c tboyer --override-channels
RUN conda install -c rdkit -c conda-forge rdkit --override-channels
# install pip package
RUN pip3 install --upgrade pip
RUN pip3 install gunicorn
上記以外にも、Dockerfileのコマンドはいろいろあります。
FROM 元になるimage名
RUN docker build時に実行するコマンド
CMD docker コンテナ起動時に実行するコマンド
ENTRYPOINT コンテナ起動時に実行するコマンド
ONBUILD imageを再利用してbuildするときに実行するコマンド
ENV 環境変数=値
WORKDIR 作業ディレクトリ
USER ユーザ名
LABEL ラベル名=値
EXPOSE ポート番号
ADD ホストのパス イメージのパス
COPY ホストのパス イメージのパス
VOLUME イメージのマウントポイントパス
詳しくは公式ページを参照して下さい
https://docs.docker.jp/engine/reference/builder.html
また、Dockerfileのベストプラクティスをdocker公式が公開してくれてますので読んでおきましょう
http://docs.docker.jp/engine/articles/dockerfile_best-practice.html
buildする
「docker build -t 作成するimage名 DockerfileがあるフォルダPATH」を実行することでDockerfileの内容通りにimageを作ってくれます。例えば、./minicondaフォルダにDockerfileがあって、testという名前でimageを作りたい場合は以下のようになります。
docker build test ./miniconda
コンテナを起動する
docker imagesで確認すると先程作ったimageが表示されます
> docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
test latest fc72cb7f0dd7 About 30 seconds ago 3.41GB
他のコンテナと同様、docker runで起動できます
docker run -it test
docker hubにアップロードする
作ったimageをdocker hubに登録することも出来ます。無料アカウントでは公開イメージしか作れませんが、有料アカウントであればイメージを非公開にすることも出来ます
https://docs.docker.jp/engine/userguide/dockerrepos.html
Dockerfileのデバッグ
docker公式のimageは軽量化を図るためか最小限のライブラリしか入っていませんので、普段使っているOSでインストールに使ってるコマンドが走らないというのが普通に起こります。しかも、エラー停止したときにRUNコマンドのどこで止まったのかイマイチ分かりにくいし、docker buildを実行する度にRUNコマンドの最初からやり直しになって時間がかかるなどの問題があるので、docker buildでデバッグしていくのは効率がよくありません。
そこで、docker run -itでコンソールに入ってコマンドを1つずつ実行しながら必要なライブラリをインストールしていって、上手くいったコマンドをDockerfileに書き移すというやり方が良いと思います。
https://qiita.com/pottava/items/452bf80e334bc1fee69a
4. docker desktopで使う
WindowsやMacではdocker desktopを使うことで、GUI上でdockerコンテナを管理することができます。
コンテナ一覧はアイコンの色でコンテナが起動中か分かるようになっていて、起動/停止の切り替え、CLI接続、再起動やコンテナの削除が出来るようになっています。image一覧から新たなコンテナを生成して起動することも出来ますし、docker hubに登録することも出来ますので複数のコンテナの起動/停止をちょこちょこ切り替えるような場合には便利だと思います。
5. まとめ
dockerめちゃめちゃ便利ですね。
Dockerfileで自前のimageをつくる辺りは結構苦戦しましたがマスターして使いこなしたいです。
参考にしたページ
Windows環境でvscode Remote Containers接続環境をつくる手順を解説してくれています
https://qiita.com/zaki-lknr/items/db99909ba1eb27803456
チートシートを作ってくれています
https://qiita.com/wMETAw/items/34ba5c980e2a38e548db