Dockerについてメモ
よく使うコマンド
docker-composeコマンドを使ってサービス立ち上げ
docker-compose -f docker-compose.yml up -d --build
サービスを終了する
docker-compose -f docker-compose.yml down -v
立ち上げたサービスを使ってテストを実行する(django)
docker exec <service_name> python manage.py test
dockerのインストール
linuxの環境とwindows,macosではインストール方法が違うと分かっている。それはdockerの仕様でそうなっているようだ。以下はcentos(linux)環境でインストールする方法である。
sudo yum install docker
dockerの起動
sudo systemctl start docker sudo systemctl enable docker
dockerのイメージ取得
*例えばcentos7 sudo docker pull centos:7
以下でも実行可能
docker image pull NAME:TAG
dockerに含まれるimageの確認
以下のコマンドを実行するとdockerに含まれるイメージを表示する事ができる。 この表示にはIMAGE IDが含まれる。このIDはイメージの削除の際に必要である。
sudo docker images
docker image ls #これでも一覧する事ができる。
イメージとコンテナの関係はクラスとオブジェクトの関係と同じ。実行環境を定義したもの。 イメージはソフトウェアのテンプレートを指し、コンテナはイメージを実体化したものである。 コンテナはDockerイメージを実行して実際に作成された環境。
起動中のコンテナを一覧表示する
コンテナの一覧を以下のコマンドで表示することができる。以下のコマンドを実行すると各コンテナのIDも表示される。 このコンテナIDはコンテナを起動する際に利用するので、コンテナを一覧表示する以下のコマンドは重要である。
sudo docker ps
過去に起動したのも含めたコンテナの一覧表示は-aオプションを使う。
sudo docker ps -a
以下の方法でも同じように実行できる。
docker container ls docker container ls -a
コンテナの生成
sudo docker run -it -name dockerName centos:7 /bin/bash # 使い方: docker run [オプション] イメージ [コマンド] [引数...]
run — Docker-docs-ja 19.03 ドキュメント
コンテナの起動
sudo docker start 35634736 * sudo docker start (containerID)
以下の方法でも実行できる。
docker container run IMAGE:TAG
コンテナの停止
sudo docker stop 35634736 * sudo docker stop (containerID)
docker container stop (containerID) #これでも実行できる
イメージの作成
sudo docker commit (container ID) イメージ名:タグ
Dockerfileを元にイメージを作成する場合は以下のコマンド
docker build (Dickerfileディレクトリ)
イメージ、コンテナの削除
dockerからimageを削除する場合にはrmiコマンドを使う。コンテナを削除する場合には、rmコマンドを使う。ただし、コンテナを消す前にイメージを削除するとエラーが生じる。かならずコンテナを消してからイメージを削除する。
sudo docker rm 31435454 *sudo docker rm (containerID) sudo docker rmi 2e39r908r04 *sudo docker rmi (IMAGE ID)
イメージの削除として以下もある。
docker image rm (IMAGEID)
docker image prune #これは使われていないイメージを削除するコマンド
コンテナの削除として以下もある。
docker container rm (containerID)
Dockerfile
コンテナに直接接続してimageを更新すると、どうimageが加工されたか把握できない。これを把握するにはどう加工したかを記録に残せば良い。Dockfileには命令を記述してどうコンテナを加工したのかを可視化する。
コンテナと仮想マシンの違い
カーネルを共有しているかどうか。
疑問
Dockerイメージは軽量な方が良いとされているが、これはなぜなのか? 自分が考えるにimageがない場合はimageをダウンロードしなければならない。軽量な方がダウンロードが早くすみ開発しやすくなる??
doker-compose -コンテナの起動
docker-compose up -d --build
Imageを作成しコンテナを起動するコマンド。docker-compose.ymlからimageをダウンロードまたは作成してそれを元にコンテナを起動している。
docker-copose.yml内にbuildがあるけど、 ここにDockerfileが存在するディレクトリを書くらしい。そうするとDockerfileを読み込んでimageを作成するようだ。 docker-compose コマンドまとめ - Qiita
doker-compose -コンテナ起動の結果確認
docker-cpmpose up —build -dコマンドの結果、つまり"コンテナが起動されたか"を確認するためにdocker psコマンドを使っても確認することができない。
docker-compose ps
上記のコマンドでコンテナの起動状況を確認する事ができる。表示のうちstateを見ると確認できる。
Name Command State Ports -------------------------------------------------------------------- mydockertest_db_1 docker-entrypoint.sh postgres Exit 1 mydockertest_web_1 python manage.py runserver ... Exit 1
stateがUpであればコンテナが起動している。
stateがExit 数字の場合はエラーが発生して起動していない状態を表す。
エラー内容を確認するのは docker-compose logs {Name} 以下のコマンドで確認する事ができる。
#全部のコンテナのエラーを確認したい時 docker-compose logs #指定したコンテナのエラーを確認したい時 docker-compose logs {Name}
Dockerfileの使い方
Dockerfileを作成したらこのファイルに基づいてImageをビルドすることは分かった。dockerfileは今の所2種類の方法でimageをビルドする方法がわかった。 一つはdockerのコマンドからdockerfileを使ってビルドする方法。もう一つはdocker-compose.yml内にdockerfileを読み込む命令を記述してimageをビルドする方法である。
dockerコマンドで実行する方法は以下のようにする。
#docker build (dockerfileが存在するディレクトリ) docker build ./
docker-compose.ymlで書く方法はBuild命令を記述する。
Dockerfileの使い方-COPY
COPY命令(instruction)はホストのリソースをコンテナにコピーする役割をもつ。
#COPY ホストのコピーしたいリソース コンテナのコピー先 COPY . usr/src/app
ンテナ側であるコピー先のパスは相対パスでもいいし、絶対パスでも良いようだ。相対パスの場合WORKDIRからの相対パスとなる。
Dockerfile リファレンス — Docker-docs-ja 19.03 ドキュメント
ちなみにホスト側のカレントディレクトリはdocker-compose.ymlで読み込まれてdockerfileがビルドされる状況下でもdockerfileが存在するディレクトリがカレントディレクトリとなる。要するにいかなる場合でもDockerfileのディレクトリ。
エラー1
Docker-compose upを実行して以下のエラーが出る
ERROR: In file './docker-compose.yml', service must be a mapping, not a NoneType.
インデントがおかしい場合に表示されたのでインデントをチェックする。
エラー2
Docker-compose upを実行して以下のエラーが出る
ERROR: yaml.scanner.ScannerError: while scanning for the next token found character '\t' that cannot start any token
'\t'はタブを示しており、ymlではタブの記述は禁止されていることからdocker-compose.ymlでエラーが生じる。
インデントを使い階層構造を表現する。ただし、インデントにはタブが使えずスペースのみが使える。スペース2個単位でインデントすることが多い。
エラー3
docker-compose up コマンドを実行後、コンテナの状態を確認したところコンテナが起動していなかった。そこでdocker-compose logsを実行すると以下のエラーコードが表示された。
Error: Database is uninitialized and superuser password is not specified. db_1 | You must specify POSTGRES_PASSWORD to a non-empty value for the db_1 | superuser. For example, "-e POSTGRES_PASSWORD=password" on "docker run".
自分はpostgresをイメージに使っており、docker-compose.ymlで
db: image: postgres volumes: - postgres_data:/var/lib/postgresql/data environment: - DATABASE_DB=docker_test_db - DATABASE_USER=docker_test_user - DATABASE_PASSWORD=docker_pass - DATABASE=postgres
と表記していた。これらが原因だ。postgresは事前に用意した環境変数を使ってもらいたい意図があるようだ。
db: image: postgres volumes: - postgres_data:/var/lib/postgresql/data environment: - POSTGRES_DB=docker_test_db - POSTGRES_USER=docker_test_user - POSTGRES_PASSWORD=docker_pass - DATABASE=postgres
これで再度コンテナの起動を試みたところ無事コンテナを起動する事ができた。
エラー4
docker-compose up --build後にpython manage.py migrateを行っているのにテーブルが生成されない事例が発生。ただしデータベースはできている。。。
django.db.utils.OperationalError: could not translate host name "postgres" to address: Name does not resolve #さらには psycopg2.OperationalError: could not translate host name "postgres" to address: Name does not resolve
を確認した。これはdocker-compose.ymlの環境変数"DATABASE_HOST"の属性値が不適切であったことから生じたようだ。
services: web: build: ./web command: python manage.py runserver 0.0.0.0:8000 ports: - 8000:8000 #volumes: # - ./web/:/usr/src/app/ environment: - SECRET_KEY=bev$oyboo9ei%oewns3_6k0v-2qoq)(-5!85z2ir15p6vio - DEBUG=1 - DATABASE_ENGINE=django.db.backends.postgresql - DATABASE_DB=docker_test_db - DATABASE_USER=docker_test_user - DATABASE_PASSWORD=docker_pass - DATABASE_HOST=localhost #ココが原因 - DATABASE_PORT=5432 depends_on: - db db: image: postgres volumes: - postgres_data:/var/lib/postgresql/data environment: - POSTGRES_DB=docker_test_db - POSTGRES_USER=docker_test_user - POSTGRES_PASSWORD=docker_pass - DATABASE=postgres
以下の記事によるとDATABASE_HOSTはサービス名を値としなければならないようだ。だからこの場合はdbが正しい。
- DATABASE_PASSWORD=docker_pass - DATABASE_HOST=db #ココが原因 - DATABASE_PORT=5432
参考; Dockerで入れたPostgreSQLへのPDO接続でエラーが出て悩んだ。 - Qiita
ドッカーのドキュメントでもデータベースを司るサービス名をdjangoのsettings.pyのHOSTの値としていることが確認できる。 Redirecting…