開発環境で使う Docker / docker-for-development

Ca17a082a30f4cbfed1d0a6dacbe3af2?s=47 shin1x1
September 29, 2018

開発環境で使う Docker / docker-for-development

2018/09/29 第24回 中国地方DB勉強会

Ca17a082a30f4cbfed1d0a6dacbe3af2?s=128

shin1x1

September 29, 2018
Tweet

Transcript

  1. 開発環境で使う Docker 2018/09/29 第24 回 中国地方DB 勉強会 @shin1x1

  2. 本発表について 技術検証、開発環境での Docker 利用を想定 本番環境による運用は対象外 Kubernetes 、デプロイ、オーケストレーション、クラウドサービ ス Linux コンテナが対象

    Docker for Mac で検証
  3. Agenda Docker 基礎 postgres イメージで理解する タスク実行環境として使う Web アプリケーション開発環境として使う

  4. Docker 基礎

  5. Docker とは コンテナを利用してアプリケーションを開発、展開、実行する プラットフォーム 軽量な仮想環境 分離されたプロセス コンテナは、ホスト OS のカーネルを利用 Linux

    コンテナには、Linux カーネルが必要 Windows コンテナには、Windows カーネルが必要
  6. Build once, Run anywhere

  7. 開発環境で Docker を使う利点 軽量 分離 ポータブル 豊富な部品、拡張性 "works on my

    machine" を解決
  8. イメージとコンテナ イメージ アプリケーション実行環境パッケージ コード、ランタイム、ライブラリ、環境変数などを内包 コンテナ イメージの実行インスタンス

  9. Docker コンテナ実行の流れ $ docker run hello-world Hello from Docker! This

    message shows that your installation appears to be working correctly. (snip) docker run コマンドでイメージからコンテナを生成して実行 hello-world : 実行するイメージ
  10. hello-world 出力メッセージ 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.
  11. hello-world 出力の流れ(図)

  12. Docker 実行環境 サーバ(デーモン)クライアント型 $ docker version Client: Version: 18.06.1-ce API

    version: 1.38 Go version: go1.10.3 OS/Arch: darwin/amd64 # macOS Server: Engine: Version: 18.06.1-ce API version: 1.38 (minimum version 1.12) OS/Arch: linux/amd64 # Linux
  13. Docker サーバ コンテナ実行ランタイム Linux コンテナでは、Linux カーネルが必要 Docker for Mac は、Linux

    VM を内包 (HyperKit) Docker クライアント docker コマンド 各 OS ネイティブアプリケーション リモートホストの Docker デーモンも操作可
  14. DockerHub Docker イメージリポジトリ Docker イメージの GitHub のようなもの 数多くのイメージが公開されている public と

    private https://hub.docker.com/explore/
  15. hello-world イメージ https://hub.docker.com/_/hello-world/

  16. of cial イメージ Docker, Inc. がレビューした公認イメージ OS (ディストリビューション)等のベースイメージ centos ,

    ubuntu , amazonlinux , alpine など 言語やミドルウェアなど人気のあるイメージ postgres , mysql , mariadb , redis php , golang , openjdk , python , ruby , node nginx , httpd https://hub.docker.com/explore/
  17. 野良イメージの危険性 利用したイメージが裏でコイン発掘してたら? OSS と似た問題 自己判断 バイナリなので気づきにくい 対策 of cial イメージを利用

    信頼できる作者、イメージを利用 自作
  18. postgres イメージを触ってみる

  19. PostgreSQL 10 イメージ実行 $ docker run --rm --name db -p

    5432:5432 postgres:10 docker run : コンテナ実行コマンド --rm : コンテナ終了後に破棄 --name : コンテナに名前を付ける(db ) -p : ポートをバインド(ホスト: コンテナ) postgres:10 : PostgreSQL 10 イメージ
  20. ホストの psql で接続 $ psql --version psql (PostgreSQL) 9.6.5 $

    psql -Upostgres -h localhost psql (9.6.5, server 10.5 (Debian 10.5-1.pgdg90+1)) WARNING: psql major version 9.6, server major version 10. Some psql features might not work. Type "help" for help. postgres=#
  21. postgres:10 コンテナで接続 $ docker exec -it db psql -Upostgres psql

    (10.5 (Debian 10.5-1.pgdg90+1)) Type "help" for help. postgres=# 実行中のdb コンテナの中で、psql を実行 -it : 対話的な操作が必要なコマンドで指定 psql / mysql シェル(sh, bash, zsh 等々)、less など
  22. DockerHub - postgres サポートバージョン、Docker le 11 、10.5 、9.6 など 利用方法

    設定項目 環境変数による指定(POSTGRES_DB など) 拡張方法 https://hub.docker.com/_/postgres/
  23. 環境変数によるパラメータ指定 指定できる主な環境変数 POSTGRES_USER : データベースユーザ POSTGRES_PASSWORD : パスワード POSTGRES_DB :

    データベース名 POSTGRES_INITDB_ARGS : initdb オプション -e で指定 $ docker run -e POSTGRES_DB=app \ -e POSTGRES_USER=db_user \ -e POSTGRES_PASSWORD=pass \ --rm --name db -p 5432:5432 postgres:10
  24. 指定した情報で接続 $ psql -Udb_user -h localhost app Password for user

    db_user: psql (9.6.5, server 10.5 (Debian 10.5-1.pgdg90+1)) Type "help" for help. app=# localhost は trust $ docker exec -it db psql -Udb_user app psql (10.5 (Debian 10.5-1.pgdg90+1)) Type "help" for help. app=#
  25. ロケール設定 postgres のロケールは en_US.utf8 ja_JP.UTF-8 にしたい $ docker exec -it

    db psql -Upostgres -l Name | Owner | Encoding | Collate | Ctype | Access privileges -----------+----------+----------+------------+------------+----------------------- postgres | postgres | UTF8 | en_US.utf8 | en_US.utf8 | template0 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres + | | | | | postgres=CTc/postgres template1 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres + | | | | | postgres=CTc/postgres
  26. ロケールを設定するイメージを作成 Docker le # ベースイメージ FROM postgres:10 # ロケール設定 RUN

    localedef -i ja_JP -c -f UTF-8 \ -A /usr/share/locale/locale.alias ja_JP.UTF-8 # 環境変数 LANG 設定 ENV LANG ja_JP.utf8
  27. イメージをビルド $ docker build -t shin1x1/postgres-ja . Sending build context

    to Docker daemon 2.048kB Step 1/3 : FROM postgres:10 ---> 084ec18124c8 Step 2/3 : RUN localedef -i ja_JP -c -f UTF-8 -A /usr/share/locale/locale.alias ja ---> Running in eaaf657d6f9e Removing intermediate container eaaf657d6f9e ---> 596109416105 Step 3/3 : ENV LANG ja_JP.utf8 ---> Running in 42486f844eca Removing intermediate container 42486f844eca ---> ef5972a28e05 Successfully built ef5972a28e05 Successfully tagged shin1x1/postgres-ja:latest
  28. shin1x1/postgres-ja を実行 $ docker run --rm --name db \ -p

    5432:5432 shin1x1/postgres-ja データベースシステム内のファイルの所有者は"postgres" となります。 (snip) $ docker exec -it db psql -Upostgres -l データベース一覧 名前 | 所有者 | エンコーディング | 照合順序 | Ctype( 変換演算子) | アクセス権限 -----------+----------+------------------+------------+-------------------+----------- postgres | postgres | UTF8 | ja_JP.utf8 | ja_JP.utf8 | template0 | postgres | UTF8 | ja_JP.utf8 | ja_JP.utf8 | =c/postgre | | | | | postgres=C template1 | postgres | UTF8 | ja_JP.utf8 | ja_JP.utf8 | =c/postgre | | | | | postgres=C
  29. コンテナのデータを永続化 ホストの pgdata ディレクトリをマウント コンテナの initdb で生成したデータを ホストに格納 $ docker

    run --rm --name db -p 5432:5432 \ -v `pwd`/pgdata:/var/lib/postgresql/data postgres -v : ホストのファイルパスをコンテナにマウント ホストの./pgdata を/var/lib/postgresql/data に マウント
  30. ホストのpgdata にデータディレクトリに $ ls pgdata PG_VERSION pg_dynshmem pg_multixact pg_snapshots pg

    base pg_hba.conf pg_notify pg_stat pg global pg_ident.conf pg_replslot pg_stat_tmp pg pg_commit_ts pg_logical pg_serial pg_subtrans pg
  31. 設定ファイルを差し替え ホストのpgdata にあるpostgresql.conf を変更 $ vim max_connections postgresql.conf #max_connections =

    100 max_connections = 200 コンテナを実行すると設定が反映されている $ docker exec db psql -Upostgres -c 'show max_connections' max_connections ----------------- 200 (1 row)
  32. テーブルを再生成 $ docker exec -it db psql -Upostgres postgres=# create

    table users(id serial, name test); CREATE TABLE postgres=# \d List of relations Schema | Name | Type | Owner --------+--------------+----------+---------- public | users | table | postgres public | users_id_seq | sequence | postgres (2 rows)
  33. コンテナを破棄して、再実行しても残っている $ docker run docker run --rm --name db -p

    5432:5432 -v `pwd`/pgdata:/var/lib/postgresql/data postgres $ docker exec -it db psql -Upostgres postgres=# \d List of relations Schema | Name | Type | Owner --------+--------------+----------+---------- public | users | table | postgres public | users_id_seq | sequence | postgres (2 rows)
  34. docker-compose コンテナ実行設定をYAML で記述 docker-compose.yml 複数コンテナを一度に管理 nginx + php-fpm + PostgreSQL

    pgpool + PostgreSQL master + standby docker-compose コマンドで操作
  35. docker-compose.yml postgres イメージを db サービスとして実行 version: '3' # docker-compose バージョン

    services: db: # サービス設定 image: postgres # イメージ environment: # 環境変数 POSTGRES_USER: db_user POSTGRES_PASSWORD: pass POSTGRES_DB: app volumes: # ボリューム - ./pgdata:/var/lib/postgresql/data # ホストをマウント ports: # ポート - "5432:5432" # ホストとマッピング
  36. サービス起動 $ docker-compose up [service] サービス起動(バックグラウンド) $ docker-compose up -d

    [service] サービス停止、破棄 $ docker-compose down [service] サービス内でコマンド実行 $ docker-compose exec [service] [command]
  37. 複数サービス連携 コンテナ間はサービス名で通信できる postgres サービスに、pgcli や adminer で接続 pgcli: リッチな psql

    adminer: データベース操作 Web アプリケーション
  38. version: '3' services: db: image: postgres:10-alpine environment: - POSTGRES_USER=app -

    POSTGRES_PASSWORD=pass - POSTGRES_DB=app pgcli: # pgcli 用サービス image: pygmy/pgcli depends_on: - db adminer: # adminer 用サービス image: adminer ports: - 8080:8080 depends_on: - db
  39. タスクの実行環境

  40. タスクの実行環境 実行環境をコンテナ(イメージ)で用意 常に同じ環境で実行できる どこでも実行できる コンテナはステートレスな実行環境として利用 入力はコンテナ外から、出力はコンテナ外に タスク終了後は、コンテナを破棄 ホスト環境を汚さない ビルド、CI/CD 、バッチ処理など

  41. JavaScript / CSS ビルド npm イメージで、Web アプリケーションアセットをビルド 入力 = ホストをマウント、出力

    = ホストに出力 常に同じ環境でビルドできる $ tree -L 1 . ├── README.md ├── docker-compose.yml ├── package.json ├── public # docroot ファイル └── src # JavaScript / CSS
  42. docker-compose.yml version: '3' services: node: image: node:8 volumes: - ./:/app

    working_dir: /app npm バージョン確認 $ docker-compose run node npm -v 5.6.0
  43. ビルド実行 # 依存解決 $ docker-compose run node npm install #

    ビルド実行 $ docker-compose run node npm run build ビルド結果 $ tree -L 1 . ├── README.md ├── build # 生成されたビルド結果 ├── docker-compose.yml ├── node_modules ├── package.json ├── public └── src
  44. curl ビルド Amazon Linux 環境で利用する libcurl.so を生成 openssl を有効にする ビルドスクリプトを書いて、amazonlinux

    コンテナでビルド Mac で ELF バリナリを生成 $ docker run --rm -v `pwd`:/opt -w /opt amazonlinux:1 \ /bin/sh build.sh $ file build/lib/libcurl.so build/lib/libcurl.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamica
  45. 開発環境の構築

  46. Web アプリケーション開発環境 PHP + Laravel WebAPI アプリケーション コードはホスト ホストの開発ツール(IDE 等)が使える

    実行環境はコンテナ 構成 nginx php-fpm PostgreSQL
  47. nginx ホストでは、8000 ポートでアクセス ホストのアプリケーションコード、設定ファイルをマウント php-fpm に依存 nginx: image: nginx:1.12 ports:

    - '8000:80' volumes: - .:/var/www/html - ./docker/nginx/nginx.conf:/etc/nginx/nginx.conf - ./docker/nginx/conf.d:/etc/nginx/conf.d depends_on: - php-fpm
  48. PHP (php-fpm) build で Docker le を指定(実行時にビルド) ホストのアプリケーションコード、設定ファイルをマウント db と

    db-test に依存 php-fpm: build: "./docker/php-fpm/" # Dockerfile のパスを指定 volumes: - .:/var/www/html - ./docker/php-fpm/php.ini:/usr/local/etc/php/conf.d/zzmyphp.ini - ./docker/php-fpm/php-fpm.conf:/usr/local/etc/php-fpm.d/zzmyphp-fpm.conf depends_on: - db - db-test
  49. php-fpm Docker le 拡張を追加したイメージをビルド FROM php:7.2-fpm # Install PHP extensions

    RUN apt-get update && apt-get install -y \ libpq-dev \ && rm -r /var/lib/apt/lists/* \ && docker-php-ext-install \ pdo_pgsql \ pgsql \ opcache
  50. composer PHP の依存解決を行うサービス composer: image: composer volumes: - .:/var/www/html working_dir:

    /var/www/html 依存解決実行 $ docker-compose run composer install
  51. PostgreSQL db = アプリケーション用 db-test = 自動テスト用 db: &db image:

    postgres:10-alpine environment: - POSTGRES_USER=app - POSTGRES_PASSWORD=pass - POSTGRES_DB=app - LC_ALL=C db-test: # db と同じ設定 <<: *db
  52. アプリケーション接続設定 アプリケーション (.env) DB_CONNECTION=pgsql DB_HOST=db DB_PORT=5432 DB_DATABASE=app DB_USERNAME=app DB_PASSWORD=pass 自動テスト

    (phpunit.xml) データベースホストをテスト用に変更 <env name="DB_HOST" value="db-test"/>
  53. アプリケーションセットアップ(Docker 関連) # 依存解決 $ docker-compose run composer install #

    キー生成 $ docker-compose exec php-fpm php artisan key:generate # データベースマイグレーション $ docker-compose exec php-fpm php artisan migrate # テストデータ投入 $ docker-compose exec php-fpm php artisan db:seed
  54. 面倒なので、Make le に書く 自動テストも含む all: install test .PHONY: all install:

    docker-compose up -d cp .env.example .env chmod -R a+w storage/* docker-compose run composer install --prefer-dist --no-interaction docker-compose exec php-fpm php artisan key:generate docker-compose exec php-fpm php artisan migrate docker-compose exec php-fpm php artisan db:seed .PHONY: install test: docker-compose run php-fpm ./vendor/bin/phpunit .PHONY: test
  55. make を実行するだけ 環境がセットアップ後に自動テストでチェック テストが通る状態から開発開始 $ make docker-compose up -d Creating

    network "web-application_default" with the default driver Creating web-application_db_1 ... done (snip) PHPUnit 7.1.2 by Sebastian Bergmann and contributors. ..................... 21 / 21 (100%) Time: 6.24 seconds, Memory: 20.00MB OK (21 tests, 53 assertions)
  56. ソースコードと一緒に管理 Git 等の VCS で管理 . ├── .git ├── Makefile

    ├── app ├── docker-compose.yaml # Git リポジトリに含める チェックアウトして、make するだけ $ git clone repo $ cd repo $ make
  57. Disposable な開発環境を目指す いつでも再構築できる開発環境 = いつでも捨てられる 環境構築の自動化 データベース含む(マイグレーション、テストデータ投入) 開発環境を秘伝のタレ にしない 誰でもどこでも同じ環境を作れる

    CI 環境にもそのまま持っていける
  58. Docker for Mac 遅い問題 Docker for Mac 遅い != Docker

    遅い マウントしたホストファイルへのアクセスで遅い フレームワーク利用時など大量のファイルがある osxfs + HyperKit + Linux VM の問題 PC スペックによっても違う
  59. Docker for Mac 遅い問題 - 解決策 Docker for Mac 再起動

    docker system prune アプリケーションの書き込みは、コンテナ内に書き込む ボリュームマウントのキャッシュ設定
  60. ボリュームマウントのキャッシュ設定 consistent : 完全な一貫性(デフォルト) cached : ホストが正。コンテナ側では遅延する場合がある。 ホストに置くソースコード delegated :

    コンテナが正。ホスト側では遅延する場合がある。 コロン: の後ろに指定 php-fpm: build: "./docker/php-fpm/" volumes: - .:/var/www/html:cached # cached を指定
  61. cached の効果 phpunit の実行時間 実行時間が、61% に短縮 バラツキはある。 キャッシュ 実行時間 比

    consistent(default) 3.97s - cached 2.42s 0.61
  62. さいごに 手軽に使えるコンテナ環境 Disposable にする デファクトスタンダード プラットフォーム、ツール、情報が充実

  63. Q? @shin1x1

  64. 参考 https://docs.docker.com/get-started/ http://docs.docker.jp/get-started/toc.html https://github.com/moby/hyperkit https://hub.docker.com/ https://docs.docker.com/docker-for-mac/osxfs/ https://docs.docker.com/docker-for-mac/osxfs-caching/