LoginSignup
2
1

More than 1 year has passed since last update.

dockerの使い方メモ

Last updated at Posted at 2021-05-07

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

2021-04-30_15-17-53.gif
-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

上記のようなコンテナを停止したい場合は以下のようにして停止できます。

UUIDで停止
docker stop 17d7dedd1195
NAMEで停止
docker stop condescending_johnson

3-6. 生成済みのコンテナを起動する

docker stopで停止したコンテナを再度起動することが出来ます

起動のみ
> docker start condescending_johnson

dockerコンテナのCLIにアクセスしたい場合は-aオプションを付けます

terminal接続で起動
> docker start -a condescending_johnson

3-7. 生成済みのコンテナを削除する

要らなくなったコンテナはdocker rmコマンドで削除できます。
削除対象はUUIDまたはNAMEで指定します。

対象を指定して削除する
docker rm condescending_johnson

使っていないコンテナをまとめて削除することも出来ます

起動してないコンテナをすべて削除する
docker container prune

使った後にいちいち消すのが面倒な場合は実行時に-rmオプションを付けて終了時にコンテナを削除するように出来ます

-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を指定して削除します

REPOSITORYを指定
docker rmi alpine/git
IMAGE_IDを指定
docker rmi c99c7d810bc1

起動していないimageをまとめて削除することも出来ます

docker image prune --all

3-10. CPU配分、メモリ上限を指定する

デフォルトではCPUとメモリは無制限になります
https://docs.docker.jp/config/container/resource_constraints.html

CPU

CPUコア数を1.5に指定する
docker run --cpus=1.5 centos
CPU配分を50%にする(1024で100%)
docker run --cpu-shares=512 centos

メモリ

--memoryでメモリ使用量上限、--memory-swapでメモリスワップの上限+メモリ使用量上限を指定します

メモリ上限512MB、メモリスワップ上限512MB
docker run --memory=512m --memory-swap=1g centos

--memory-swapを省略すると-memoryの値をスワップ上限に使います。
つまり上記の場合は--memory-swapを省略しても同じになります。

メモリ上限512MB、メモリスワップ上限512MB
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を入れて実行したコマンドそのものを標準エラー出力に出すようにしておきましょう。

miniconda/Dockerfile
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のコマンドはいろいろあります。

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を作りたい場合は以下のようになります。

terminal
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

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1