# Docker 入門 ## もくじ ## 1. Docker って何? > Docker は、アプリケーションをすばやく構築、テスト、デプロイできるソフトウェアプラットフォームです。 - [AWS](https://aws.amazon.com/jp/docker/) より引用 らしいです。 あとマスコットキャラクターが可愛いです。 ![](https://i.imgur.com/IIxD4AC.png) 可愛いね ## 2. Hyper-V とかとの違い よく仮想化技術なんて言われ方をしていますが、では Hyper-V(WSL2) とはどのように異なるのでしょうか?それは以下の図を見れば一目瞭然です。 <div style="text-align: center"> <img src="https://i.imgur.com/ZyCSKgG.png"> <p> (出典: https://www.itmedia.co.jp/enterprise/articles/1612/19/news041.html) </p> </div> このように、Hyper-V なんかはカーネル(OS)単位で仮想化がされますが、Docker では1つの OS 上で複数のコンテナが動作します。これにより、1つの1つのコンテナのサイズが軽く、起動・停止等も高速にすることができるようになります。Hyper-V も仮装環境としては確実ですが、これはサイズが大きくなってしまい、また起動・停止も時間を要するので Docker を使うことが多いのです。 ## 2. Docker で何ができるの? 大きく分けて(私の経験上)以下の3つです 1. Ubuntu や Arch Linux などの OS の仮装環境を立て、その OS 上でのアプリの挙動を確かめることができる 2. devcontainer で開発環境を一発で立てることができる(1の応用) 3. docker-compose で複数のコンテナ(サービス)から成るシステムを一発で立ち上げることができる 今回はこれら3つを実際に体験し、Docker の知識を深めてみましょう。 ## 3. 演習 ### (0) Docker のインストール(for ubuntu) インストールされてるか確認 ```console $ docker run hello-world ``` されてなかったら https://hackmd.io/@szpp/rkM66Dg5d#1-Docker ### (1) Alpine Linux を docker で動かしてみよう #### 1 Alpine Linux とは?  Linux ディストリビューション(Ubuntu とか Arch Linux とか)の1つで、めちゃくちゃ軽量であることが特徴です。Ubuntu が 700MB であるのに対して Alpine Linux はたったの 100MB で、コンテナのサイズも軽くすることが多いので Linux のコンテナを作りたいときは使われることが結構多いです。 #### 2. alpine linux の立ち上げ ```console $ docker run -it alpine:3.14 sh ``` - docker ... docker のコマンド - run ... 新しいコンテナを実行する - -i ... ホストの入力をコンテナの標準出力をつなげる => キーボードから入力したときにそれがコンテナ上の画面に表示されるようになる - -t ... コンテナの標準出力とホストの出力をつなげる => コンテナの出力が見れるようになる - sh ... コンテナが起動したときに実行するコマンド。今回はシェルを起動したいので `sh` #### 3. コンテナの OS 情報確認 ```console $ uname -a Linux c08f93fba5c8 5.10.47-linuxkit #1 SMP PREEMPT Sat Jul 3 21:50:16 UTC 2021 x86_64 Linux ``` ### (2) szpp-todo-app-sample の開発環境を Docker で整えてみよう #### 0-1. szpp-todo-app-sample の clone ```console $ git clone https://gitlab.com/arumakan1727/szpp-todo-app-sample.git $ code szpp-todo-app-sample ``` #### 0-2. Remote Development 拡張機能のインストール ![](https://i.imgur.com/x0veNyz.png) #### 1. szpp-todo-app-sample の開発において必要なもの - go - node.js - npm - yarn 1からやる人だと開発環境構築に1時間ぐらいかかりそうなので docker で整えてあげましょう。 #### 2. devcontainer とは VScode の標準機能で devcontainer というものがあります。devcontainer は docker のコンテナを作成してそこに VScode のサーバーをインストールし、コンテナ上で VScode を動かすことができるよーというものです。 これは以下の点でかなり嬉しいサービスです。 - コンテナ上で VScode を動かせる - ローカルの ssh の設定がコンテナ上に引き継がれる - VScode の拡張機能までインストールさせることができる 今回はこれを使って開発環境を構築していきます。 #### 3. `.devcontainer` の準備 devcontainer はプロジェクト内に `.devcontainer/` があれば動かすことができます。`.devcontainer/` は `Dockerfile` と `devcontainer.json` の2つのファイルで構成されるので、それぞれを準備していきましょう。 ##### 3-1. Dockerfile Dockerfile は Docker のイメージの内容を記述するためのファイルです。 Docker には Ubuntu とか Alpine とか大元となる OS のイメージは転がっていますが、あくまでそれらはバニラの OS に過ぎないので、Go や Node.js など自分が欲しいアプリケーションは自分で用意しなければなりません。そんなときに使うのがこの Dockerfile ということです。 では、Dockerfile を記述してみましょう。...と言いたいところですが、一つ一つ説明していると時間がなくなってしまうので以下の Dockerfile を `.devcontainer/Dockerfile` にコピペしてください。 ```dockerfile= FROM ubuntu:20.04 ENV DEBIAN_FRONTEND=noninteractive # 色々なアプリケーションのインストール RUN apt-get update && \ apt-get install -y \ build-essential \ wget \ tar \ git && \ apt-get clean && rm -rf /var/lib/apt/lists/* # タイムゾーンの設定 RUN apt-get update && \ apt-get install -y tzdata && \ apt-get clean && rm -rf /var/lib/apt/lists/* ENV TZ Asia/Tokyo ## Go のインストール RUN \ wget https://golang.org/dl/go1.17.1.linux-amd64.tar.gz && \ tar -C /usr/local -xzf go1.17.1.linux-amd64.tar.gz ## node.js + npm のインストール RUN \ apt-get update && \ apt-get install -y nodejs npm && \ npm install n -g && \ n stable && \ apt purge -y nodejs npm && \ apt-get clean && rm -rf /var/lib/apt/lists/* ## yarn のインストール RUN npm install yarn -g RUN useradd -m -s /bin/bash -U vscode USER vscode ENV PATH /usr/local/go/bin:$PATH ``` 以下に簡単な説明を置いておきます。 - `FROM [イメージ]:[タグ]` ... ベースとなるイメージ:タグ - `ENV [key]=[value]` ... 環境変数(export よりもこっちの方がいい) - `RUN [command]` ... **イメージ作成時(docker build)** に実行するコマンド - `USER [user]` ... ユーザーを切り替える - `ENTRYPOINT [command]` ... **コンテナ起動時(docker run)** に実行するコマンド ##### 3-2. devcontainer.json devcontainer に関するあれこれを設定するファイルです。よくいじるフィールドは `extensions` と `remoteUser` の2つだと思いますが、今回は `extensions` だけ扱います。 `extensions` は VScode の拡張機能を設定するフィールドです。今回の devcontainer で使いたい拡張機能は以下の通りです。 - `golang.go` ... Golang - `johnsoncodehk.volar` ... Vue.js - `mosapride.zenkaku` ... 全角が強調される これらを `extensions` にセットすればコンテナ上の VScode で利用可能となります。 ```json "extensions": [ "golang.go", "johnsoncodehk.volar", "mosapride.zenkaku" ], ``` #### 4. devcontainer の起動 これで準備は整いました。左下の `><` みたいなボタンを押して `Reopen in Container` を選択すれば devcontainer が起動します。(結構時間がかかるかも) #### 5. 開発できる環境であるかを確認 **各種コマンド** ```console $ go version go version go1.17.1 linux/amd64 $ npm -v 6.14.15 $ yarn -v v14.17.6 ``` **拡張機能** go や vue のファイルで補完が出るか(go だと install/update tools しないとかも) ### (3) szpp-todo-app-sample を docker-compose で一発で立ち上げてみよう。 #### docker-compose.yaml ```yaml= version: "3" services: backend: build: context: back-end dockerfile: Dockerfile restart: always container_name: todo-app-backend environment: - HOGE=hogehoge ports: - "8080:8080" frontend: build: context: front-end dockerfile: Dockerfile container_name: todo-app-frontend depends_on: - backend ports: - "5000:5000" ``` 一応 docker-compose.yaml の本質はこれです。  #### front-end/Dockerfile ```dockerfile= FROM node:16 WORKDIR /workdir COPY yarn.lock tsconfig.json package.json /workdir/ RUN yarn global add serve RUN yarn install --no-progress COPY public /workdir/public COPY src /workdir/src COPY index.html /workdir/ COPY vite.config.ts /workdir/ RUN yarn build ENTRYPOINT [ "serve", "-s", "dist" ] ``` #### back-end/Dockerfile ```dockerfile= FROM golang:1.17 AS build WORKDIR /work COPY . . RUN \ CGO_ENABLED=0 \ GOOS=linux \ go build -o app FROM ubuntu:20.04 WORKDIR /work RUN \ apt-get update && \ apt install -y tzdata && \ apt-get clean && rm -rf /var/lib/apt/lists/* ENV TZ Asia/Tokyo RUN \ apt-get update && \ apt install -y ca-certificates && \ apt-get clean && rm -rf /var/lib/apt/lists/* COPY --from=build /work/app app ENTRYPOINT [ "./app" ] ``` #### ビルド & 起動 ```console $ docker-compose up -d --build ``` #### 確認 ##### front-end http://localhost:5000 ##### back-end ```console $ curl localhost:8080/api/todo ```