Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

Docker 基礎

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

Build once, Run anywhere

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

Docker コンテナ実行の流れ $ docker run hello-world Hello from Docker! This message shows that your installation appears to be working correctly. (snip) docker run コマンドでイメージからコンテナを生成して実行 hello-world : 実行するイメージ

Slide 10

Slide 10 text

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.

Slide 11

Slide 11 text

hello-world 出力の流れ(図)

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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/

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

postgres イメージを触ってみる

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

ホストの 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=#

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

環境変数によるパラメータ指定 指定できる主な環境変数 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

Slide 24

Slide 24 text

指定した情報で接続 $ 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=#

Slide 25

Slide 25 text

ロケール設定 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

Slide 26

Slide 26 text

ロケールを設定するイメージを作成 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

Slide 27

Slide 27 text

イメージをビルド $ 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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

コンテナのデータを永続化 ホストの pgdata ディレクトリをマウント コンテナの initdb で生成したデータを ホストに格納 $ docker run --rm --name db -p 5432:5432 \ -v `pwd`/pgdata:/var/lib/postgresql/data postgres -v : ホストのファイルパスをコンテナにマウント ホストの./pgdata を/var/lib/postgresql/data に マウント

Slide 30

Slide 30 text

ホストの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

Slide 31

Slide 31 text

設定ファイルを差し替え ホストの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)

Slide 32

Slide 32 text

テーブルを再生成 $ 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)

Slide 33

Slide 33 text

コンテナを破棄して、再実行しても残っている $ 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)

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

タスクの実行環境

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

ビルド実行 # 依存解決 $ 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

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

開発環境の構築

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

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

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

アプリケーションセットアップ(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

Slide 54

Slide 54 text

面倒なので、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

Slide 55

Slide 55 text

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)

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

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

Slide 62

Slide 62 text

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

Slide 63

Slide 63 text

Q? @shin1x1

Slide 64

Slide 64 text

参考 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/