開発と本番環境でのDocker活用：初心者の視点

## はじめに
こんにちは！エアークローゼットのTadaです。この記事は、[エアークローゼットアドベントカレンダー2024](https://qiita.com/advent-calendar/2024/air-closet)の21日目の記事です。

エアークローゼットで1年ほどの経験を持つソフトウェアエンジニアとして、開発プロセスをスムーズかつ効率的にするための強力なツールをいくつか活用してきました。その中でも特に重要なのがDockerです。Dockerは、特にマイクロサービスアーキテクチャにおいて、現代のソフトウェア開発において欠かせないツールとなっています。エアークローゼットでもこのアーキテクチャを目指しており、私自身Dockerの基本を学びながら、それがチームにどのような利便性をもたらしているかを実感しています。

この記事では、Dockerの基本について説明し、macOSでDockerを使用するためのいくつかのヒントを共有します。経験は浅いですが、私の視点と学んだ知識がDocker初心者やプロジェクトへの導入を検討している方々にとって役立つことを願っています。

![2021-02-11-docker-tips-and-best-practices.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3935565/6bba3f61-45ed-3ce7-e546-c1ff682564bf.png)

## 1. Dockerとは何か？簡単な紹介
Dockerは、アプリケーションをコンテナという形で開発、配布、実行するためのプラットフォームです。コンテナは軽量で独立した実行可能なソフトウェアパッケージで、アプリケーションを動かすために必要なコード、ランタイム、ライブラリ、システムツールをすべて含んでいます。アプリケーションを「コンテナ化」することで、開発者の環境やテスト環境、本番環境にかかわらず、一貫して動作させることが可能になります。

Dockerが登場する前は、アプリケーションのデプロイ時に依存関係を手動でインストールする必要があり、開発、テスト、本番環境間での不整合が生じやすい状況でした。Dockerはアプリケーションとその依存関係をコンテナにまとめることで、この問題を解決し、どこでも一貫して動作するソフトウェアを実現しています。

### Dockerの主要な概念：
- **Dockerfile**：Dockerイメージを作成するための手順を定義したテキストファイルです。ベースイメージや依存関係のインストール方法、アプリケーションの実行方法などが記載されています。
- **イメージ**：Dockerイメージはコンテナの設計図であり、アプリケーションを動作させるために必要なすべてを含んでいます。
- **コンテナ**：Dockerイメージの実行インスタンスです。コンテナはホストシステムや他のコンテナから隔離されています。
- **Docker Compose**：複数のコンテナで構成されるDockerアプリケーションを定義および管理するためのツールです。1つのコマンドで複数のコンテナを開始、停止、構成できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3935565/01486d41-43af-0c33-12e9-c9a130f80d8d.png)


## 2. macOSでのDocker導入：始め方
エアークローゼットでは主にmacOSを使用しており、最初はmacOSでDockerを動作させるのに少し苦労しました。Dockerコンテナは通常Linux上で動作するためです。しかし、Docker Desktop for macOSを使用すれば、軽量なLinux仮想マシン（VM）を利用して簡単にコンテナを実行できます。

### Dockerをインストールする手順
1. **Docker Desktopのダウンロード**
   Dockerの公式ウェブサイトから[Docker Desktop](https://docs.docker.com/desktop/setup/install/mac-install/)をダウンロードします。IntelとApple Silicon（M1/M2）両方に対応しています。

2. **Docker Desktopのインストール**
   ダウンロードしたインストーラーを使ってDockerをアプリケーションフォルダにドラッグ＆ドロップします。インストール後、アプリケーションフォルダからDockerを起動できます。

3. **Dockerのインストール確認**
   ターミナルを開いて以下のコマンドを実行し、Dockerが正しくインストールされているか確認します：

   ```bash
   docker --version
   docker run hello-world
   ```
   2つ目のコマンドはテストコンテナを実行し、すべてが正常に動作しているか確認します。「Dockerが正常にインストールされました」というメッセージが表示されれば成功です。

4. **Docker Desktopの設定**
   Docker Desktop for macOSは仮想マシン内で動作します。Docker Desktopの設定で、仮想マシンに割り当てるCPUやRAMなどのリソースを調整できます。これにより、コンテナを効率的に実行するためのリソースを確保できます。

## 3. Dockerのヒントとトリック
### 3.1. Docker Desktopの代わりにColimaを使用する
Docker DesktopはmacOSで広く使われていますが、非常に重いツールです。Apple Siliconは非常に強力ですが、作業中にマシンがかなり熱くなることがあります。この問題を解決するために、[Orbstack](https://orbstack.dev/)や[Colima](https://github.com/abiosoft/colima) などの選択肢があります。オープンソースソフトウェアのファンので、Colima を使用しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3935565/905c8a04-15bd-acce-9328-48f030708f70.png)

#### Colimaを選ぶ理由：
- **低オーバーヘッド**：Docker Desktopのグラフィカルインターフェースが不要なため、高速で軽量です。
- **シンプルなセットアップ**：コマンドラインを介して設定でき、ミニマリストなアプローチを好む人には特に便利です。
- **リソース効率**：リソースの少ないマシンでのローカル開発に最適です。

#### Colimaのインストール方法
Homebrewを使用してColimaをインストールできます：

```bash
brew install colima
```

インストール後、以下のコマンドでColimaを起動します：

```bash
colima start
```

Colimaを起動したら、通常のDocker CLIコマンドを使用できます。以下のコマンドで動作確認ができます：

```bash
docker info
```

正しく設定されていれば、DockerプロバイダーとしてColimaが表示されます。

### 3.2. VSCodeでDockerコンテナに接続して開発
Dockerの強力な機能の1つは、開発環境を直接コンテナ内で実行できることです。これにより、マシン間で開発環境を一貫させ、依存関係を分離することが可能です。

VSCodeのRemote - Containers拡張機能を使用すれば、実行中のDockerコンテナに簡単に接続して開発できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3935565/28d3cd2d-2845-d525-8efb-521b6c9e3330.png)
#### VSCodeとDockerのセットアップ手順：
1. **Remote - Containers拡張機能のインストール**
   VSCodeを開き、拡張機能マーケットプレイスで"Remote - Containers"を検索してインストールします。

2. **開発環境用のDockerfileを作成**
   必要な環境を設定するDockerfileを作成します。たとえば、Node.js環境の場合：

   ```Dockerfile
   FROM node:14

   WORKDIR /app

   COPY package.json package-lock.json ./
   RUN npm install

   COPY . .

   CMD ["npm", "start"]
   ```

3. **.devcontainerフォルダを追加**
   プロジェクトディレクトリに.devcontainerフォルダを作成し、その中にdevcontainer.jsonファイルを作成します。このファイルでVSCodeがコンテナを開くための設定を行います：

   ```json
   {
     "name": "Node.js Development",
     "dockerFile": "Dockerfile",
     "extensions": [
       "dbaeumer.vscode-eslint",
       "ms-azuretools.vscode-docker"
     ],
     "workspaceFolder": "/app"
   }
   ```

4. **プロジェクトをVSCodeで開く**
   devcontainer.jsonファイルが設定されていれば、コマンドパレット（macOSではCmd + Shift + P）を使用して`Remote-Containers: Reopen in Container`と入力し、プロジェクトを再オープンできます。

   VSCodeがコンテナをビルドして接続します。これにより、Dockerfileで定義した環境内で作業できます。

### 3.3. Dockerビルドの最適化
Docker開発における一般的な課題は、ビルド時間とイメージサイズを削減することです。以下は、Dockerfileを最適化するためのいくつかのヒントです：

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3935565/eb531a0f-a900-348c-71ea-e850eb9af5aa.png)


- **マルチステージビルドを使用**：ビルドプロセスと最終ランタイムイメージを分離することで、最終イメージのサイズを削減できます。

   ```Dockerfile
   # ビルドステージ
   FROM node:14 AS builder
   WORKDIR /app
   COPY package.json package-lock.json ./
   RUN npm install

   # 本番ステージ
   FROM node:14-slim
   WORKDIR /app
   COPY --from=builder /app /app
   CMD ["npm", "start"]
   ```

- **レイヤーを最小化**：Dockerfile内の各`RUN`、`COPY`、`ADD`コマンドは新しいレイヤーを作成します。可能であればコマンドを組み合わせてください：

   ```Dockerfile
   RUN apt-get update && apt-get install -y curl git
   ```

- **.dockerignoreファイルを使用**：.gitignore と似ており、このファイルは Docker ビルドプロセス中に無視するファイルを指定し、不必要なコピーを減らします。

### 3.4 CI/CD で Docker ビルドを自動化する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3935565/32a3daed-41f9-8f26-4ea8-bee12f4ea8fc.png)
本番環境では、CI/CD パイプラインを使用して Docker ビルドを自動化することが重要です。GitHub Actions、Circle CI、Jenkins などの CI ツールと Docker を統合することで、ワークフローを効率化し、環境間の一貫性を確保できます。例えば、GitHub Actions を使用して Docker ビルドを自動化すると、リポジトリへのコミットごとに新しいイメージが構築され、コンテナレジストリにプッシュされるようになります。

## 4. マイクロサービスにおいて、Dockerは非常に重要な役割を果たしています。
マイクロサービスアーキテクチャは、スケーラブルで管理しやすく、独立したシステムを構築するための標準となっています。このアーキテクチャでは、アプリケーションを小規模で緩やかに結合されたサービスに分解することで、管理やスケーリングが容易になります。Docker は特にマイクロサービスにおいて有用であり、各サービスをコンテナ化し、依存関係を独立して管理する手段を提供します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3935565/3e05a49a-f298-c88f-4894-57961d36d2bc.png)

#### マイクロサービスに Docker が不可欠な理由
- **分離と独立性**: 各サービスは他のサービスから独立して実行されます。
- **一貫した環境**: 開発、テスト、本番環境で一貫性が確保されます。
- **スケーラビリティ**: サービスごとに独立してスケーリングが可能です。
- **CI/CD の向上**: 自動化されたパイプラインが簡単に設定できます。
- **ネットワークの簡略化**: Docker の組み込みネットワーキング機能により、サービス間の通信が容易になります。

## 5. 結論: 私たちの旅において、Dockerは重要なツールとなります
Docker やマイクロサービスの世界に比較的最近足を踏み入れた身として、Docker がもたらす力と柔軟性に感銘を受けています。アプリケーションをコンテナ化し、開発から本番環境までのパイプラインを簡素化する Docker の能力は、信頼性が高くスケーラブルなシステムを構築する上で重要な役割を果たしています。まだ未熟な部分もあるかもしれませんので、もし不足している点があれば、ぜひコメントで教えていただけると嬉しいです。

## P.S.
最後まで読んでいただき、ありがとうございます！

[エアークローゼットアドベントカレンダー2024](https://qiita.com/advent-calendar/2024/air-closet)はまだまだ続きますので、ぜひ他のエンジニア、デザイナー、PMの記事もご覧いただければと思います

また、エアークローゼットはエンジニア採用活動も行っておりますので、興味のある方はぜひご覧ください！

https://corp.air-closet.com/recruiting/developers/

https://www.wantedly.com/companies/airCloset/projects