初学者によるDocker理解まとめ②　〜docker-composeまで〜

# はじめに
ようやくDockerを学び始めんたので自分の理解をまとめておく。
前回 => https://qiita.com/theFirstPenguin/items/c9ae28c795a884a40aa6
次回 => https://qiita.com/theFirstPenguin/items/b6d3e414e829e68e23ae

# 今日の学びをメモ
node.jsでexpressを実行するコンテナを立ち上げる。たったこれだけをdocker-composeを使ってやってみた。

![スクリーンショット 2020-10-22 11.29.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/572098/9cc47dea-2418-e456-d323-4d55595ebe71.png)

## まずはローカルで準備
```
cd ~
mkdir sample && cd sample
yarn init -y
yarn add express
touch index.js
```

```index.js
const express = require('express');
const app = express();
app.get('/', (req, res) => {
  res.send('Hello').status(200);
});

app.listen(3000, () => {
  console.log('Listening on port 3000');
});
```
```
node index.js
```



当然ですが、ローカルでcurlコマンドを叩くと返事が帰ってきますね。

```
curl http://localhost:3000
Hello
```
一応、いまの状況を図化します。一応ね。
![スクリーンショット 2020-10-22 11.49.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/572098/70557836-9217-8a1f-8f21-45ea313c8d29.png)

## Dockerfileの準備
node.jsのdockerイメージをつくることきは[ここを参照する](https://nodejs.org/en/docs/guides/nodejs-docker-webapp/)。今回はコピペ。sampleディレクトリ直下に下記のDockerfileを作る。

```Dockerfile:Dockerfile
FROM node:alpine

# Create app directory
WORKDIR /usr/src/app

# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+)
COPY package*.json ./

RUN npm install
# If you are building your code for production
# RUN npm ci --only=production

# Bundle app source
COPY . .
# package.jsonをコピー後にnpm installするという作業をビルドの度に毎回やりたくない。
# そのため、上記を終わらせてから COPY. .をやる。
# そうすればコードを変えた部分だけビルドが実行される。

EXPOSE 3000
CMD [ "node", "index.js" ]
```

そして、node_modulesもコピーされると辛いので、`.dockerignore`も作っておく。

```
touch .dockerignore
echo 'node_modules' >> .dockerignore
```

ちなみに、ここまでくれば、別にdocker-composeを使わなくても

```
docker build -t app .
docker run -p 3000:3000 app
```
をすればコンテナが立ち上がります。
今回は上記コマンドを使わず、docker-composeによってコンテナを立ち上げます。

## docker-compose.ymlの準備
sampleディレクトリ直下に下記のdocker-compose.ymlを作る。

```docker-compose.yml
version: '3'
#何も考えず3を指定

services:
#コンテナに関する情報を記述。ここに複数のコンテナ情報を書くことで、複数のコンテナを同時に起動できる
  app:
  # appという（DNSの名前空間を持つ）コンテナを立ち上げる。
    build:
    # ビルド時の情報をここに記載する。Dockerfileがあればそれを参照できるし、なければ直接ここに書く。
      context: .
      # ビルド時にこのdocker-compose.ymlと同じディレクトリ（.）にあるDockerfileを参照する。
      # Dockerfileが複数ある場合は、ディレクトリを分けてcontextに指定する、もしくはその名前を docokerfile：XXX として指定する必要がある。
    container_name: express-app
    # 任意のコンテナ名をつける。このコンテナ名を使って、下記コマンドでコンテナにアクセスすることができる
    # docker exec -it express-app sh
    ports:
      - '3000:3000'
    # docker run -p 3000:3000 と一緒の意味です。
    volumes:
      - './:usr/src/app'
    # ローカルPCのカレントディレクトリ（./）とコンテナの~/usr/src/appディレクトリを同期させる
    # 開発にとっても便利。
```

## docker-compose up して終わり
`docker-compose up`すればコンテナが立ち上がります。
ローカルPCからcurlコマンドを打てばコンテナから返事が帰ってきます。最初の図の通りです。

```
curl http://localhost:3000
Hello
```
![スクリーンショット 2020-10-22 13.30.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/572098/ceeea304-f837-289d-dadb-5f100cb90668.png)



コンテナを止めるには`docker-compose down`をします。`index.js`の中身を書き換えるなどした際は、 `docker-compose build`で再ビルドします。

また、`docker-compose up -d`とすればバックグラウンドでコンテナが立ち上がるんですが、このときはコンテナ内の `console.log`が見えづらかったりするので、自分はフォアグラウンドが好きです。

# 最後に
初歩中の初歩をまとめました。ありがとうございました。