diadia

興味があることをやってみる。自分のメモを残しておきます。

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のイメージ取得

Docker Hub

*例えば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個単位でインデントすることが多い。

YAML覚書 - Qiita

エラー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…