$30 off During Our Annual Pro Sale. View Details »

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

shin1x1
September 29, 2018

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

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

shin1x1

September 29, 2018
Tweet

More Decks by shin1x1

Other Decks in Technology

Transcript

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

    View Slide

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

    Linux
    コンテナが対象
    Docker for Mac
    で検証

    View Slide

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

    View Slide

  4. Docker
    基礎

    View Slide

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

    View Slide

  6. Build once, Run anywhere

    View Slide

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

    View Slide

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

    View Slide

  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 :
    実行するイメージ

    View Slide

  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.

    View Slide

  11. hello-world
    出力の流れ(図)

    View Slide

  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

    View Slide

  13. Docker
    サーバ
    コンテナ実行ランタイム
    Linux
    コンテナでは、Linux
    カーネルが必要
    Docker for Mac
    は、Linux VM
    を内包 (HyperKit)
    Docker
    クライアント
    docker
    コマンド
    各 OS
    ネイティブアプリケーション
    リモートホストの Docker
    デーモンも操作可

    View Slide

  14. DockerHub
    Docker
    イメージリポジトリ
    Docker
    イメージの GitHub
    のようなもの
    数多くのイメージが公開されている
    public
    と private
    https://hub.docker.com/explore/

    View Slide

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

    View Slide

  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/

    View Slide

  17. 野良イメージの危険性
    利用したイメージが裏でコイン発掘してたら?
    OSS
    と似た問題
    自己判断
    バイナリなので気づきにくい
    対策
    of cial
    イメージを利用
    信頼できる作者、イメージを利用
    自作

    View Slide

  18. postgres
    イメージを触ってみる

    View Slide

  19. PostgreSQL 10
    イメージ実行
    $ docker run --rm --name db -p 5432:5432 postgres:10
    docker run :
    コンテナ実行コマンド
    --rm :
    コンテナ終了後に破棄
    --name :
    コンテナに名前を付ける(db

    -p :
    ポートをバインド(ホスト:
    コンテナ)
    postgres:10 : PostgreSQL 10
    イメージ

    View Slide

  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=#

    View Slide

  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
    など

    View Slide

  22. DockerHub - postgres
    サポートバージョン、Docker le
    11
    、10.5
    、9.6
    など
    利用方法
    設定項目
    環境変数による指定(POSTGRES_DB
    など)
    拡張方法
    https://hub.docker.com/_/postgres/

    View Slide

  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

    View Slide

  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=#

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    マウント

    View Slide

  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

    View Slide

  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)

    View Slide

  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)

    View Slide

  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)

    View Slide

  34. docker-compose
    コンテナ実行設定をYAML
    で記述
    docker-compose.yml
    複数コンテナを一度に管理
    nginx + php-fpm + PostgreSQL
    pgpool + PostgreSQL master + standby
    docker-compose
    コマンドで操作

    View Slide

  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" #
    ホストとマッピング

    View Slide

  36. サービス起動
    $ docker-compose up [service]
    サービス起動(バックグラウンド)
    $ docker-compose up -d [service]
    サービス停止、破棄
    $ docker-compose down [service]
    サービス内でコマンド実行
    $ docker-compose exec [service] [command]

    View Slide

  37. 複数サービス連携
    コンテナ間はサービス名で通信できる
    postgres
    サービスに、pgcli
    や adminer
    で接続
    pgcli:
    リッチな psql
    adminer:
    データベース操作 Web
    アプリケーション

    View Slide

  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

    View Slide

  39. タスクの実行環境

    View Slide

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

    View Slide

  41. JavaScript / CSS
    ビルド
    npm
    イメージで、Web
    アプリケーションアセットをビルド
    入力 =
    ホストをマウント、出力 =
    ホストに出力
    常に同じ環境でビルドできる
    $ tree -L 1
    .
    ├── README.md
    ├── docker-compose.yml
    ├── package.json
    ├── public # docroot
    ファイル
    └── src # JavaScript / CSS

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  45. 開発環境の構築

    View Slide

  46. Web
    アプリケーション開発環境
    PHP + Laravel WebAPI
    アプリケーション
    コードはホスト
    ホストの開発ツール(IDE
    等)が使える
    実行環境はコンテナ
    構成
    nginx
    php-fpm
    PostgreSQL

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  50. composer
    PHP
    の依存解決を行うサービス
    composer:
    image: composer
    volumes:
    - .:/var/www/html
    working_dir: /var/www/html
    依存解決実行
    $ docker-compose run composer install

    View Slide

  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

    View Slide

  52. アプリケーション接続設定
    アプリケーション (.env)
    DB_CONNECTION=pgsql
    DB_HOST=db
    DB_PORT=5432
    DB_DATABASE=app
    DB_USERNAME=app
    DB_PASSWORD=pass
    自動テスト (phpunit.xml)
    データベースホストをテスト用に変更

    View Slide

  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

    View Slide

  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

    View Slide

  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)

    View Slide

  56. ソースコードと一緒に管理
    Git
    等の VCS
    で管理
    .
    ├── .git
    ├── Makefile
    ├── app
    ├── docker-compose.yaml # Git
    リポジトリに含める
    チェックアウトして、make
    するだけ
    $ git clone repo
    $ cd repo
    $ make

    View Slide

  57. Disposable
    な開発環境を目指す
    いつでも再構築できる開発環境 =
    いつでも捨てられる
    環境構築の自動化
    データベース含む(マイグレーション、テストデータ投入)
    開発環境を秘伝のタレ にしない
    誰でもどこでも同じ環境を作れる
    CI
    環境にもそのまま持っていける

    View Slide

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

    View Slide

  59. Docker for Mac
    遅い問題 -
    解決策
    Docker for Mac
    再起動
    docker system prune
    アプリケーションの書き込みは、コンテナ内に書き込む
    ボリュームマウントのキャッシュ設定

    View Slide

  60. ボリュームマウントのキャッシュ設定
    consistent :
    完全な一貫性(デフォルト)
    cached :
    ホストが正。コンテナ側では遅延する場合がある。
    ホストに置くソースコード
    delegated :
    コンテナが正。ホスト側では遅延する場合がある。
    コロン:
    の後ろに指定
    php-fpm:
    build: "./docker/php-fpm/"
    volumes:
    - .:/var/www/html:cached # cached
    を指定

    View Slide

  61. cached
    の効果
    phpunit
    の実行時間
    実行時間が、61%
    に短縮
    バラツキはある。
    キャッシュ 実行時間 比
    consistent(default) 3.97s -
    cached 2.42s 0.61

    View Slide

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

    View Slide

  63. Q?
    @shin1x1

    View Slide

  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/

    View Slide