Docker hands on

2a3710646ca647dccd379703f2713682?s=47 koda
July 13, 2019

Docker hands on

- 7/13のGCPUGで行った、Dockerハンズオンの資料です

2a3710646ca647dccd379703f2713682?s=128

koda

July 13, 2019
Tweet

Transcript

  1. 6.
  2. 10.

    Server Host OS Hypervisor GuestOS Bins/Libs App1 GuestOS GuestOS Bins/Libs

    App3 App2 Server Host OS Docker Bins/Libs App1 App2 Bins/Libs App3 Bins/Libs ハイパーバイザ型 コンテナ型 起動まで2分(OSを起動・初期化をする必要があり) 起動まで1秒 早 い
  3. 11.

    Server Host OS Hypervisor GuestOS Bins/Libs App1 GuestOS GuestOS Bins/Libs

    App3 App2 Server Host OS Docker Bins/Libs App1 App2 Bins/Libs App3 Bins/Libs ハイパーバイザ型 コンテナ型 2250MB 550MB 軽 い 50MB 200MB 500MB 50MB 200MB 500MB 50MB 200MB 500MB 50MB 200MB 50MB 50MB 200MB
  4. 12.

    Server Host OS Hypervisor GuestOS Bins/Libs App1 GuestOS GuestOS Bins/Libs

    App3 App2 Server Host OS Docker Bins/Libs App1 App2 Bins/Libs App3 Bins/Libs ハイパーバイザ型 コンテナ型 管理しやすい 作業手順書 初期セットアップ 更新作業 VMを保守していくな運用 (秘伝のタレ) Dockerfile Docker build コンテナは使い捨て バージョンアップはイメージ再生性 ビルドしたイメージを配布 DockerfileはGitで管理(Infrastructure as Code)
  5. 13.

    Dockerの基本用語 ✘ Dockerイメージ ◦ Dockerコンテナを作成するためのベースのイメージ ✘ Dockerコンテナ ◦ 実際に動いている実態 ◦

    オブジェクト指向のClassとInstanceの関係に近い Nginx Image Site-A container Site-B container docker run --name sitea nginx Student(Class) Suzuki(Instance) Tanaka(Instance) Suzuki = new Student()
  6. 15.

    FROM buildpack-deps:jessie RUN groupadd --gid 1000 node \ && useradd

    --uid 1000 --gid node --shell /bin/bash --create-home node ENV NODE_VERSION 8.16.0 RUN ARCH= && dpkgArch="$(dpkg --print-architecture)" \ && case "${dpkgArch##*-}" in \ amd64) ARCH='x64';; \ ppc64el) ARCH='ppc64le';; \ s390x) ARCH='s390x';; \ arm64) ARCH='arm64';; \ armhf) ARCH='armv7l';; \ i386) ARCH='x86';; \ *) echo "unsupported architecture"; exit 1 ;; \ esac \ # gpg keys listed at https://github.com/nodejs/node#release-keys && set -ex \ && for key in \ 94AE36675C464D64BAFA68DD7434390BDBE9B9C5 \ FD3A5288F042B6850C66B31F09FE44734EB7990E \ 71DCFD284A79C3B38668286BC97EC7A07EDE3FC1 \ DD8F2338BAE7501E3DD5AC78C273792F7D83545D \ C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 \ B9AE9905FFD7803F25714661B63B535A4C206CA9 \ 77984A986EBC2AA786BC0F66B01FBB92821C587A \ 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \ 4ED778F539E3634C779C87C6D7062848A1AB005C \ A48C2BEE680E841632CD4E44F07496B3EB3C1762 \ B9E2F5981AA6E0CD28160D9FF13993A75599653C \ ; do \ gpg --batch --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys "$key" || \ gpg --batch --keyserver hkp://ipv4.pool.sks-keyservers.net --recv-keys "$key" || \ gpg --batch --keyserver hkp://pgp.mit.edu:80 --recv-keys "$key" ; \ done \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH.tar.xz" \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \ && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \ && grep " node-v$NODE_VERSION-linux-$ARCH.tar.xz\$" SHASUMS256.txt | sha256sum -c - \ && tar -xJf "node-v$NODE_VERSION-linux-$ARCH.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \ && rm "node-v$NODE_VERSION-linux-$ARCH.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs ENV YARN_VERSION 1.15.2 : : Sample: Node.jsのイメージの Dockerfile https://github.com/nodejs/docker-node/blob/7e47b378c42b03ae6afae704c5bf5b724aae2b92/8/jessie/Dockerfile ハンズオンのあとで、実際に Dockerfileを書いてみるので、こ こでは雰囲気がわかれば OK
  7. 27.

    Dockerコンテナを起動してみる 27 以下を実行 $ docker run --name nginx -p 80:80

    nginx:alpine localhost にアクセスできたら 「Ctrl + C」で終了
  8. 28.

    起動のパラメータを変えてみる 28 以下を実行 $ docker run -d --rm --name nginx2

    -p 81:80 nginx docker run : Dockerコンテナを作成して起動する -d : デーモン起動 --rm: 停止時にコンテナを削除 --name: コンテナに名前をつける -p 81:80: コンテナの80ポートで起動しているサービスを、ホストの 81ポートで公開する nginx: nginxイメージを起動
  9. 29.

    よく使うDockerコマンド 29 $ docker logs -f {container-name or container-id} -

    コンテナのログ(colsoleにはかれたもの)を確認 - 「-f」 は `tail -f` と同じオプションで、ログを監視して新たなログが出力されたら表示する - デーモン起動したコンテナのログを確認するのに便利 Tips - DockerではアプリケーションがConsoleに出力した内容をログファイルに保存していく - このログをカスタマイズすることも可能 - Logging Driver という仕組み - 例えば、ログローテーションするとか - `docker run` に --log-opt max-size=[0-9]+[kmg] --log-opt max-file=[0-9]+ といったオプション - ログをfluentdに連携するなどのオプションも取れる - Docker時代のアプリケーションは、アプリケーションはログの管理をしなくて良い(Consoleに出力すればOKで、ログの ローテーションなどはDockerが行う) - https://docs.docker.com/config/containers/logging/configure/
  10. 30.

    30 よく使うDockerコマンド $ docker pull {image-name}:{tag} - Docker imageを取得する -

    `docker run` のときに、指定のイメージが無ければ pull してくれるのであまり明示的にこの コマンドを使うことは無いかも Tips - DockerのImageはDockerHubで検索するといろいろある - pullするImageは、同じイメージでもTagで、バージョンを指定したりベースのOSを指定できる - 「alpine」のタグがあるものがあれば、容量が小さいので積極的に使おう - 例: nginxの通常のイメージは100MBくらいだけど、alpineを使えば20MBくらい - ただし、「alpine」だと動かない場合もあるので、その場合、Tagに「Slim」がついているものを探すと良い - 自分が開発するアプリ(Node.jsやJava)だと動かない事が多い、、、 - DBとかNginx、アプリが利用するものはalpineで問題ないことが多い
  11. 31.

    よく使うDockerコマンド 31 $ docker images - 現在持っているDockerイメージを確認する $ docker ps

    - 現在動いているdockerコンテナを確認する $ docker ps -a - 停止したコンテナも含めてコンテナを確認する
  12. 32.

    よく使うDockerコマンド 32 $ docker images - 現在持っているDockerイメージを確認する $ docker ps

    - 現在動いているdockerコンテナを確認する $ docker ps -a - 停止したコンテナも含めてコンテナを確認する Nginxコンテナが停止されている。 停止していたとしても、同じ名前のコンテナを起動することはできない。 `$ docker run --name nginx -p 80:80 nginx` ←失敗する 停止中のコンテナを起動しなおすか、停止しているコンテナを削除して再実行する (コンテナは使い捨てと考えると、基本は削除 →起動しなおしでOK)
  13. 33.

    よく使うDockerコマンド 33 $ docker start {container-name or container-id} - 停止しているコンテナを起動

    $ docker stop {container-name or container-id} - コンテナを停止 再びポート80でアクセスできる Nginx2 のコンテナは起動オプションで 「--rm」 をつけていたので、停止するとコンテ ナ自体が消える コンテナは使い捨てで使うほうが良いので、 「--rm」をつけることがオススメ
  14. 34.

    よく使うDockerコマンド 34 $ docker run {Docker image} - Dockerコンテナを、指定のDocker imageを元に作成して起動する

    ★よく使うオプション★ -d デーモン起動 --rm 停止したタイミングでコンテナを削除 --name {コンテナ名} コンテナに名前をつける(省略すると、49個の形容詞と68名の著名な科学者もしくはハッカーの名前をランダムに組み合せる) -p {公開するポート}:{コンテナのポート} コンテナで開いたポートをホスト側で公開する -v {マウントするホスト側のファイル/ディレクトリ}:{コンテナ側のファイル/ディレクトリ} ホスト側のファイル・ディレクトリを、コンテナ内にマウントする
  15. 35.

    よく使うDockerコマンド 35 docker run のよく使うオプションを試してみる docker run -d --rm --name

    nginx-volume -p 8080:80 -v `pwd`/www:/usr/share/nginx/html:ro nginx:alpine wwwディレクトリの中の index.html が表示
  16. 36.

    よく使うDockerコマンド 36 $ docker exec --it {container id or name}

    sh - 指定のコンテナに入って、コマンドを実行する - `sh` がコマンド - シェルを起動しているので、中に入って操作できる コンテナ内での操作
  17. 42.

    Docker imageをbuildしてみる 42 $ docker build [-t {image_name} [:{tag_name}}} {dockerfileのディレクトリ}

    - Dockerイメージをbuildする - tagは指定しないと「latest」になる
  18. 44.

    Dockerイメージのレイヤー構造 44 FROM node:10.16.0-stretch-slim RUN apt-get update && apt-get -y

    upgrade && apt-get -y install git WORKDIR /usr/app RUN git clone https://github.com/vuetifyjs/theme-blog.git WORKDIR /usr/app/theme-blog RUN yarn install VOLUME /usr/app/theme-blog EXPOSE 8080 CMD ["yarn", "run", "serve"] Image: node Image: node Add Git Image: node Add Git Git Clone Image: node Add Git Git Clone yarn install
  19. 45.

    Dockerイメージのレイヤー構造 45 FROM node:10.16.0-stretch-slim RUN apt-get update && apt-get -y

    upgrade && apt-get -y install git WORKDIR /usr/app RUN git clone https://github.com/creativetimofficial/vuetify-material-dashboard.git WORKDIR /usr/app/vuetify-material-dashboard RUN yarn install VOLUME /usr/app/vuetify-material-dashboard EXPOSE 8080 CMD ["yarn", "run", "serve"] FROM node:10.16.0-stretch-slim RUN apt-get update && apt-get -y upgrade && apt-get -y install git WORKDIR /usr/app RUN git clone https://github.com/vuetifyjs/theme-freelancer.git WORKDIR /usr/app/theme-freelancer RUN yarn install VOLUME /usr/app/theme-freelancer EXPOSE 8080 CMD ["yarn", "run", "serve"] すでにレイヤーが あればそれを使う
  20. 48.

    dockerfileで良く使う記述 48 FROM {image}[:{tag}] - Dockerイメージのベースになるイメージを指定する ADD {hostのディレクトリorファイル} {コンテナのディレクトリorファイル} -

    ホストのディレクトリやファイルをコンテナに追加する RUN {Linuxのコマンド} - ベースになっているLinuxでコマンドを実行 - ベースイメージによってコマンドは変わる(apt, yum, apk…) WORKDIR {コンテナ内のディレクトリ} - コンテナで操作する際のカレントディレクトリ EXPOSE {ポート番号} - そのコンテナが開くポート VOLUME {コンテナ内のディレクトリ} - コンテナ保持するボリューム(永続化) - 指定が無いと、そのディレクトリは起動時に消えてしまう USER {実行ユーザ} - 実行するユーザを指定 ENV {Key}={Value} - コンテナ内の環境変数を設定 CMD [{コマンド}] - コンテナが起動したときに実行するコマンドを指定
  21. 49.

    49 Infrastructure as Code ✘ コードでインフラ管理 ◦ 作業手順書とかで、マニュアルでインフラを構築しない ◦ コードを実行すれば、その環境を構築できる

    ✘ Dockerfileは環境構築の手順が書かれたコード ✘ これをGitで管理することで、インフラの変更の差分も管理できる
  22. 52.

    Docker Registry ✘ Dockerfileを使って作成したコンテナイメージを登録できる ◦ DockerHub ◦ プライベートなリポジトリ ◦ Third

    Party(GitLab, Google, AWS….) ✘ 公開リポジトリにはイメージがいろいろある(MySQL、 Tensorflow…) ◦ それを取得(Pull)すれば環境構築完了 ✘ 自分で作成したイメージをDockerレジストリで配布できる ◦ インストールマニュアルとかいらない
  23. 55.

    $ docker login registry.gitlab.com $ docker build -t registry.gitlab.com/ koda3t/hands-on-docker

    . $ docker push registry.gitlab.com/ koda3t/hands-on-docker Docker Registry
  24. 57.

    https://blog.docker.com/2019/07/intro-guide-to-dockerfile-best-practices/ Intro Guide to Dockerfile Best Practices Tip #1: Order

    matters for caching Tip #2: More specific COPY to limit cache busts Tip #3: Identify cacheable units such as apt-get update & install Tip #4: Remove unnecessary dependencies Tip #5: Remove package manager cache Tip #6: Use official images when possible Tip #7: Use more specific tags Tip #8: Look for minimal flavors Tip #9: Build from source in a consistent environment Tip #10: Fetch dependencies in a separate step Tip #11: Use multi-stage builds to remove build dependencies (recommended Dockerfile)
  25. 61.
  26. 64.

    version: "3" services: vote: build: ./vote command: python app.py volumes:

    - ./vote:/app ports: - "5000:80" networks: - front-tier - back-tier result: build: ./result command: nodemon server.js volumes: - ./result:/app ports: - "5001:80" - "5858:5858" networks: - front-tier - back-tier worker: build: context: ./worker depends_on: - "redis" networks: - back-tier redis: image: redis:alpine container_name: redis ports: ["6379"] networks: - back-tier db: image: postgres:9.4 container_name: db volumes: - "db-data:/var/lib/postgresql/data" networks: - back-tier volumes: db-data: Sample: docker-compose.yml
  27. 69.

    69 Docker公式のDocker-composeを使ってみる git clone https://github.com/dockersamples/example-voting-app.git ↓ docker-compose up voting-app: 投票のWebアプリ

    redis: 投票結果を一時保持 worker: 投票結果をdbへ登録 db: 結果を保存するデータベース result-app: 投票結果を表示するWebアプリ
  28. 73.

    docker-compose.ymlの説明 73 services : vote: build: ./vote command: python app.py

    volumes: - ./vote:/app ports: - "5000:80" networks : - front-tier - back-tier db: image: postgres:9.4 container_name : db volumes: - "db-data:/var/lib/postgresql/data" networks : - back-tier volumes: db-data: networks : front-tier : back-tier : サービス名 このdocker-composeの中で管理 するサービスを書くセクション サービスのDockerイメージは、 このディレクトリにあるdockerfile をビルドして作成する コンテナ起動時に実行するコマンド `vote` ディレクトリをマウント (マウントしたソースをビルド) 公開するポート このコンテナが所属するネットワーク (同一ネットワークに所属するとホスト 名で接続できる) サービスのDockerイメージ (イメージを指定しているのでBuildしない) データボリューム名(永続化) `db-data` という名前で、コンテナ内の `/var/lib/postgresql/data` ディレクトリを 永続化する Dockerで`db-data` という名前のデータボ リュームを管理する ネットワークの指定 back-tierは公開しないで、front-tier を公開している
  29. 74.

    よく使うdocker-composeのコマンド 74 $ docker-compose up [-d] [{service_name}] - Docker-composeファイルにある各サービスを起動する -

    [-d] はデーモン起動 - サービス名を指定すればそのコンテナのみを起動し、指定しない場合は全てのサービスを起動する $ docker-compose build - docker-composeファイルにbuildの定義がある場合に、ビルドを実行する $ docker-compose logs [-f] {service_name} - docker-compose.ymlにかかれている サービス名でコンテナのログを確認 $ docker-compose down - 起動している全てのコンテナを停止する $ docker-compose exec {service_name} sh - サービスの中に入る(docker exec -it {container_name} sh と同等) $ docker-compose run --rm {service} - 指定のサービスを起動する
  30. 77.

    Docker-Composeを使った開発 ✘ Docker-Composeを使うと各自の開発環境が揃う ◦ Windowsで開発したけどLinuxで動かなかった。。。 ◦ Node.jsやDBのバージョンが微妙にずれてた。。。 ✘ 開発で使っている環境で、CIを回せる ◦

    Jobを動かすサーバーに事前にミドルウェアをインストールし ておかなくても良い ◦ 今回は簡単なのでGitLabCIを使うが、CircleCIやTravisCI、 Jenkinsでも基本は同じ
  31. 78.

    ローカルでの開発 ✘ `develop-with-docker` ディレクトリにサンプル ◦ Frontend と backend で開発をするアプリの例 ✘

    README.md にセットアップなどのコマンドが書かれている ◦ Docker-composeコマンドを使う ✘ 指定のコマンドを実行すれば起動できるので、バックエンド・フ ロントエンドと担当が別れていても、お互いの最新のコードを起 動して開発が進められる ◦ モックとか作らなくて良い事が多い
  32. 80.

    ローカルでの開発 ✘ `docker-compose run --rm {service} {command}` ✘ {command} で実行するコマンドを指定できる

    ◦ 省略するとdocker-compose.ymlに書かれたコマンドを実行 ◦ それも書かれていなかったらDockerイメージのコマンドを実行 $ docker-compose run --rm backend yarn install --no-optional service command
  33. 88.

    CI (Lint/Test) with Docker-compose ①DeployのJobを実行 Docker build と Image の

    push `docker-compose.yml`を 更新(1.0.2を使う) ソースコードのProject コードにTagをうつ Webapp:1.0.1 → WebApp:1.0.2 デプロイ用のProject デプロイ指示 デプロイのパイプラインの例 Docker Registry Update docker-compose.yml (git pull) Webappを開始 (docker-compose up) デプロイ完了通知 公開している環境 チャット サービス ②Deployの完了通知 ③確認
  34. 92.

    92 GKE(Google Kubernetes Engine) ✘ Docker コンテナを実行するための強力なクラスタ管理およびオー ケストレーション システム ✘

    Google Container Engine が名前が変わった ◦ Google Container Engine の時も略称は GKE だった ✘ Amazon AWS / Microsoft Azure にも類似の Dockerコンテナをホ ストするサービスがある ◦ ベンダロックインにならないので、積極的に使っていける! ◦ 各ベンダーのPaaSを使える共通のプラットフォームがDockerや Kubernetesになってきている
  35. 105.

    105 ハンズオンで作成したイメージをGoogle用にビルド ✘ `dockerfile-test` ディレクトリに移動して実行 $ gcloud auth configure-docker $

    docker build -t gcr.io/eks-sample/eks-sample-web:v0.0.1 . $ docker push gcr.io/eks-sample/eks-sample-web:v0.0.1