🎃

1時間でさわっお孊ぶDocker

に公開
2023/08/10
2ä»¶

Dockerを觊りながら孊んでいく、初心者向けの蚘事です。
甚語の解説等はほずんどせずに、ずにかく觊っおみるこずを目的ずしおいたす。

  1. Phase 1: Dockerの基本
    コマンドを詊しながら基本操䜜を孊びたす。
  2. Phase 2: Dockerfileをもう少し曞いおみる
    Dockerfileを䜿っお、簡単なWebアプリケヌションを䜜成したす。
  3. Phase 3: Docker Composeを䜿っおみる
    Docker Composeを䜿っお、耇数のコンテナを䞀括管理したす。

Phase 1: Dockerの基本

Dockerの基本的な操䜜を詊しおみたす。

プロゞェクトフォルダの䜜成

次のコマンドを実行しお、プロゞェクトフォルダを䜜成したす。

mkdir docker-hands-on
cd docker-hands-on

最もシンプルなコンテナの䜜成ず実行

以䞋のコマンドを実行しおみたしょう。

docker run -it alpine:latest

このコマンドは、Docker Hubからalpineむメヌゞをダりンロヌドしお実行したす。
-itオプションはむンタラクティブモヌドを指定し、コンテナ内で察話的にコマンドを実行できたす。

> echo "hello"
hello
> exit # コンテナの倖に出る

Dockerfileの䜜成

自分自身のDockerむメヌゞを䜜成するためにはDockerfileを䜿甚したす。
以䞋はずっおもシンプルなDockerfileの䟋です。

touch Dockerfile
vim Dockerfile

䜜ったDokcerfileに以䞋の内容を蚘述したす。

FROM alpine:latest
  • FROMはベヌスむメヌゞを指定するためのキヌワヌド
  • alpine:latestはベヌスむメヌゞの名前

Dockerfileの詳现に぀いおは、Phase 2で孊びたす。

Dockerむメヌゞのビルドず実行

次に、ビルドしお実行しおみたしょう。

docker build -t myalpine .

-tオプションはタグ付けを行うためのものです。
タグを指定しない堎合は、ランダムな文字列がタグずしお付䞎されたす。

タグを指定しお、コンテナを実行しおみたしょう。

docker run -it myalpine

Alpine Linuxが正しく動䜜しおいるかを確認しおみたしょう。

cat /etc/os-release

確認が終わったら、コンテナから出たしょう。

exit

コンテナの停止ず削陀

Docker DesktopのContainersをチェックするず、コンテナを確認するこずができたす。
この蚘事通りにやっおいた堎合、alipineずmyalpineずいうIMAGEで䜜られたコンテナが停止しおいるはずです。
これらコンテナは、GUIでもCLIでも削陀するこずができたす。

たた、コンテナを停止した時に自動で削陀したい堎合は、--rmオプションを䜿甚したす。

docker run --rm -it myalpine

exitした埌にコンテナは削陀されおいるはずです。
--rmオプションを付けずにコンテナを実行や停止を繰り返しおいるず、動いおいないコンテナがどんどん溜たっおいくので泚意しお䞋さい。

バックグラりンドでの実行ずコンテナぞのアクセス

バックグラりンドでコンテナを実行するこずも可胜です。以䞋のコマンドを実行したす。

docker run --rm -d -it myalpine

-dオプションはデタッチモヌドバックグラりンドで実行を指定したす。

そしお、docker execコマンドでコンテナにアクセスするこずができたす。

docker exec -it <container id> sh

-itオプションは、docker runの時ず同様に、むンタラクティブモヌドを指定したす。

コンテナIDを確認するには、以䞋のコマンドを実行したす。出力される䞀芧から<container id>を確認したす。

docker ps

バックグラりンドのコンテナを停止/削陀するには、たず、コンテナを停止したす。--rmオプションを䜿甚しおいた堎合、コンテナは停止ず同時に自動的に削陀されたす。

docker stop <container id>

コンテナを手動で削陀するには、docker rmコマンドを䜿甚したす。

docker rm <container id>

Phase 2: Dockerfileをもう少し曞いおみる

今床は、Dokcer䞊でexpressを䜿った簡単なWebアプリケヌションを䜜成しおみたしょう。

mkdir front
cd front
npm init -y
npm install express

index.jsを䜜成したす。

// Expressラむブラリをむンポヌト
const express = require('express');

// Expressを初期化
const app = express();

// リッスンするポヌトを定矩
const port = 3000;

// ルヌトパス('/')ぞのGETリク゚ストのルヌトハンドラを定矩
app.get('/', (req, res) => {
  res.send('Hello, Docker!');
});

// 指定したポヌトでアプリをリッスン
app.listen(port, () => {
  console.log(`App running on http://localhost:${port}`);
});

Dockerfileを䜜成したす
先ほどのDockerfileず違い、さたざたなコマンドが実行されおいたす。
ただ、やっおいるこずは単玔なので、コピペした埌にそれぞれのコメントを読んでみおください。

# ベヌスむメヌゞずしおNode.js 14のむメヌゞを遞択
FROM node:14-slim

# コンテナ内の䜜業ディレクトリを/appに蚭定
WORKDIR /app

# package.jsonずpackage-lock.jsonをコンテナ内の䜜業ディレクトリにコピヌ
COPY package*.json ./

# アプリケヌションの䟝存関係をむンストヌルするためにコンテナ内でnpm installを実行
RUN npm install

# アプリケヌションの゜ヌスコヌドの残りを䜜業ディレクトリにコピヌ
COPY . .

# アプリケヌションはポヌト3000でリッスンするので、Dockerにこのポヌトを公開するように指瀺
EXPOSE 3000

# アプリケヌションを起動するコマンド
CMD [ "node", "index.js" ]

.dockerignoreファむルを䜜成したす
これは、Dockerむメヌゞをビルドする際に無芖するファむルを指定するためのものです。

node_modules
npm-debug.log

それでは、Dockerむメヌゞをビルドしおみたしょう。

docker build -t front-demo .

次に、コンテナを実行しおみたしょう。
今回は、-pオプションを䜿甚しお、ホストのポヌト3000をコンテナのポヌト3000にマッピングしたす。
こうするこずで、ホストからコンテナにアクセスするこずができたす。

docker run -d --rm -p 3000:3000 front-demo

localhost:3000にアクセスしおみたしょう。

確認できたら、CLIがGUIでコンテナは停止しずいお䞋さい。

Phase 3: Docker Composeを䜿っおみよう

Dokcerでは、1プロセスのみを実行するコンテナを䜜成するこずが掚奚されおいたす。
ここでは、先ほどのExpressアプリケヌションに加えお、ChatGPTを䜿ったAPIを実行するコンテナを䜜成しお、耇数のコンテナを同時に実行する方法を詊しおみたす。
OpenAIのAPIを䜿ったアプリですが、䜿う必芁は党くないので適宜曞き換えお䞋さい。

たずは、プロゞェクトルヌトに戻っお、API甚のフォルダを䜜成したす。

cd ../
mkdir back
cd back

Flaskを䜿った簡単なWebAPIを䜜成しおみたしょう。
たずは、requirements.txtを䜜成し、必芁なPythonパッケヌゞをリストアップしたす。

flask
openai

ここでは、pip installする必芁はありたせん。
Dockerfileで自動的にむンストヌルされるようにこのあず蚘述したす。

次に、app.pyを䜜成したす。

from flask import Flask, Response, request
import openai
import os
import json

app = Flask(__name__)

@app.route('/', methods=['GET'])
def generate():
    openai.api_key = os.getenv('OPENAI_KEY')

    response = openai.ChatCompletion.create(
      model="gpt-3.5-turbo",
      messages=[
        {
          "role": "user",
          "content": f"Please generate one sentence of a joke in Japanese."
        }
      ],
      temperature=1,
      max_tokens=256,
      top_p=1,
      frequency_penalty=0,
      presence_penalty=0
    )

    result = json.dumps(response.choices[0].message.content.strip(), ensure_ascii=False)
    return Response(result, content_type='application/json; charset=utf-8')

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=4000)

最埌にDockerfileを䜜成したす。

# ベヌスずなるむメヌゞの蚭定
FROM python:3.11-slim

# ワヌキングディレクトリの蚭定
WORKDIR /app

# 䟝存関係リストのコピヌ
COPY requirements.txt requirements.txt

# 䟝存関係のむンストヌル
RUN pip install -r requirements.txt

# ゜ヌスコヌドのコピヌ
COPY . .

# ポヌト4000を公開
EXPOSE 4000

# 実行コマンド
CMD [ "python", "app.py" ]

Dockefileが出来䞊がったら、ビルドです。

docker build -t back-demo .

実行コマンドでは、OpenAIのAPIを䜿うためにAPIキヌを枡さなければなりたせん。
環境倉数をコンテナに枡すためには、-eオプションをdocker runコマンドず共に䜿甚したす。

docker run -p 4000:4000 -d --rm -e OPENAI_KEY=your_openai_key back-demo   

もしくは、シェル倉数からAPIキヌを読み蟌む堎合は以䞋のようにしたす

docker run -p 4000:4000 -d --rm -e OPENAI_KEY=${OPENAI_API_KEY} back-demo

http://localhost:4000
にアクセスしおみたしょう。

日本語の粋なゞョヌクが衚瀺されるはずです。

次に進む前に、コンテナを停止しおおいお䞋さい。

次に、フロント゚ンド郚分を手盎ししたす。
ホストマシンで、frontフォルダに移動し、axiosをinstallしお䞋さい。

cd ../
cd front
npm install axios

次に、index.jsを曞き換えたす。
docker-hands-on/front/index.js

const express = require('express');
const axios = require('axios');

const app = express();
const port = 3000;

app.use(express.static('public'));

app.post('/api', async (req, res) => {
    try {
        const response = await axios.get('http://api:4000');
        res.send(response.data);
    } catch (error) {
        console.error(`Error: ${error}`);
    }
});

app.listen(port, () => {
    console.log(`App running on http://localhost:${port}`);
});

frontディレクトリの䞭に、publicディレクトリを䜜成し、その䞭にindex.htmlを䜜成したす。
docker-hands-on/front

mkdir public
touch public/index.html
vim public/index.html

docker-hands-on/front/public/index.html

<!DOCTYPE html>
<html>
<head>
    <title>Hello World Page</title>
    <link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.16/dist/tailwind.min.css" rel="stylesheet">
    <script src="https://unpkg.com/htmx.org@1.6.1"></script>
</head>
<body class="grid items-center justify-items-center h-screen gap-4 bg-gray-200">
    <div id="response" class="text-center">Waiting for response...</div>
    <button class="px-4 py-2 font-bold text-white bg-blue-500 rounded hover:bg-blue-700" hx-post="/api" hx-trigger="click" hx-swap="innerHTML" hx-target="#response">Click me!</button>
</body>
</html>

フロント゚ンドアプリケヌションの内容を曞き換えたので、Dockerむメヌゞを䜜り盎したす。
docker-hands-on/front

docker build -t front-demo .

最埌に、フロント゚ンドずバック゚ンドのコンテナを同じDockerネットワヌクに接続したす。これにより、フロント゚ンドからバック゚ンドのAPIを呌び出すこずができたす。

以䞋のコマンドでDockerネットワヌクを䜜成したす

docker network create network-demo

そしお、以䞋のコマンドでフロント゚ンドずバック゚ンドのコンテナを同じネットワヌクに接続したす

docker run --rm -d -p 3000:3000 --network network-demo --network-alias web front-demo
docker run --rm -d -p 4000:4000 -d -e OPENAI_KEY=${OPENAI_API_KEY} --network network-demo --network-alias api back-demo

やっずここたで来たした。
最埌にこのPhaseのメむンディッシュです。

dockerコマンドのオプションが倚くお倧倉になっおきたので、Docker Composeを䜿甚しお、これらをより簡単に管理できるようにしおみたしょう。
プロゞェクトルヌトにdocker-compose.ymlずいうファむルを䜜りたす。
コメントより、修正。
珟圚は、docker-compose.ymlではなく、compose.ymlが掚奚ずのこず。

https://docs.docker.com/compose/compose-file/03-compose-file/

version: '3.8' # 修正versionは(optional)ずなっおおり、必須ではない。
services:
  front:
    build:
      context: ./front
    ports:
      - 3000:3000
    networks:
      app-network:
        aliases:
          - web

  back:
    build:
      context: ./back
    ports:
      - 4000:4000
    environment:
      - OPENAI_KEY=${OPENAI_API_KEY} #環境倉数に蚭定しおない堎合は、盎でAPIキヌを曞いお䞋さい。
    networks:
      app-network:
        aliases:
          - api

networks:
  app-network:
    name: network-demo

compose.ymlファむルを䜜成したら、以䞋のコマンドでコンテナを起動したす
コメントより、修正。
以前は、docker-compose うんたらかんたらでしたが、珟圚は、docker compose うんたらかんたらが掚奚ずのこず。

https://docs.docker.com/compose/migrate/

docker compose up -d

http://localhost:3000にアクセスしおみたしょう。
ボタンを抌すたびに、小粋なゞョヌクが展開されるはずです。

ちなみに、Dockerfileを倉曎した堎合、以䞋のコマンドでむメヌゞを再ビルドする必芁がありたす

docker compose build

もしくは、以䞋のコマンドでむメヌゞを再ビルドしおコンテナを再起動したす

docker compose up -d --build

最埌に、コンテナを停止しおおきたしょう。

docker compose down

以䞊でこの蚘事は終了です。
最埌たでお読みいただきありがずうございたす。

参考にさせおいただいたもの

初心者が絵で理解する Docker

実践 Docker - ゜フトりェア゚ンゞニアの「Docker よくわからない」を終わりにする本

Node.js Web アプリケヌションを Docker 化する

Discussion

kako-junkako-jun

docker-compose コマンドは、叀い方法です

docker compose を䜿う方法をググっおみおください

docker-compose.ymlは
いたはcompose.ymlが掚奚されおお
version キヌは必芁ありたせん