2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ここに2つのDockerコンテナ、AとBがあったとします。Aコンテナでデータを処理したあと、Bコンテナにデータを送ります。受け取ったBコンテナは、また別の処理をし、Aコンテナへデータを返却します。この一連の流れを実現するにはどうすればいいか、実例で説明します。

説明の前に重要なポイントを洗い出します。

  • Bコンテナにアクセスするためのアドレスの指定を間違えずに行う。最重要です。

    • docker-compose.yml ファイルで2つのコンテナを起動すると、同一のネットワークが割り当てられます。

    • 同じネットワーク内のコンテナは、お互いのサービス名ネットワーク内のポート番号を使って通信を行うことができます。

  • Bコンテナが起動した後に、Aコンテナを起動させる。

    • Bコンテナはサーバーとして、Aコンテナからのデータを受け取るので、先に起動する必要があります。

    • docker-compose.yml ファイルでdepends_on で起動の順序を指定します。

  • Bコンテナから値の返却があるまで一定時間待ちます。

    • 一定時間待つ設定をしないと、値が返却される前にコンテナの起動が終了します。

それでは各コンテナの実装の流れを見ていきましょう。

Aコンテナの作成

Aコンテナの役割は、YouTubeの動画の文字起こしを取得することです。

  • YouTubeの動画のURLを指定します

  • URLからidを取得します。

  • id をもとに、Pythonのライブラリを使って動画の文字起こしを取得します。

  • 文字起こしのテキストデータをBコンテナへ送信します。

  • Bコンテナで別の処理をしたテキストデータを受け取ります。

  • 受け取ったテキストをファイルに保存します。

以上の流れを実装したスクリプトは次のようになります。

import urllib.parse
from youtube_transcript_api import YouTubeTranscriptApi
import requests

url = "https://www.youtube.com/watch?v=CJjSOzb0IYs"

parsed_url = urllib.parse.urlparse(url)
query_params = urllib.parse.parse_qs(parsed_url.query)
video_id = query_params.get("v") # returns an array including the value next to "v=..."

if video_id:
    video_id = video_id[0]
    transcript_list = YouTubeTranscriptApi.get_transcript(video_id)
    transcription = ""
    for t in transcript_list:
        transcription += " "+ t["text"]

    with open("transcription.txt", "w") as file:
        file.write(transcription)

    # Send the request and wait for the response until 5 sec
    try:
        posted = requests.post("http://punctuate_text:5000/punctuate", data={"text": transcription}, timeout=5)
        posted.raise_for_status()  # Raise an exception for non-2xx responses

        if posted.status_code == 200:
            with open("output.txt", "w") as file:
                file.write(posted.text)
    except requests.exceptions.RequestException as e:
        print("Error occurred:", e)
else:
    print("No video ID found.")

⭐️ 最も注目して欲しいのは次の1行です。

posted = requests.post("http://punctuate_text:5000/punctuate", data={"text": transcription}, timeout=5)
  • punctuate_text : 後で出てくるdocker-composeファイルで指定したBコンテナのサービス名です。

  • 5000 : 同じくdocker-composeファイルで指定したネットワーク内のポート番号です。

  • /punctuate : BコンテナのFlaskサーバーで指定したルートアドレスです。

コンテナ作成のDockerfileは次の通りです。

FROM python:3.9-slim

WORKDIR /app

COPY requirements.txt requirements.txt
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

CMD ["python3", "app.py"]

Bコンテナの作成

Bコンテナの役割は、Aコンテナから送られてきた文字起こしに句点を打つことです。

  • PytyonのFlaskを使ってサーバーを作成します。

  • 句点作成用のルートを作成します。

  • ルートに対してPOSTされたテキストデータを受け取ります。

  • テキストに対し、Pythonの自然言語処理ライブラリSpaCyを使い、句点を打ちます。

  • 句点付きテキストを返却します。

  • サーバーのポート番号5000を指定します。

以上の流れを実装したスクリプトは次のようになります。

from flask import Flask, request
import spacy

app = Flask(__name__)
nlp = spacy.load("en_core_web_sm")


@app.route('/punctuate', methods=['POST'])
def punctuate_text():
    text = request.form.get('text')
    doc = nlp(text)
    punctuated_text = ""
    for sentence in doc.sents:
        punctuated_text += sentence.text + ". "
    return punctuated_text

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

コンテナ作成のDockerfileは次の通りです。

FROM python:3.9-slim
WORKDIR /app

COPY requirements.txt requirements.txt
RUN pip install -U pip setuptools wheel
RUN pip install --no-cache-dir -r requirements.txt
RUN python -m spacy download en_core_web_sm

COPY . .

CMD ["python3", "app.py"]

Docker Composeファイルの作成

ファイル全体は次のようになります

# docker-compose.dev.yml

version: "3.8"

services:
  # Container A
  get_transcription:
    build:
      context: ./python
    container_name: transcription
    depends_on:
      - 
    volumes:
      - ./python:/app

  # Container B
  punctuate_text:
    build:
      context: ./punctuate
    container_name: punctuate
    ports:
      - 8000:5000

Aコンテナの記述で重要な箇所

depends_on:
- punctuate_text
  • Bコンテナのサービス名を指定することで、Bコンテナの後にAコンテナを起動することができます。

Bコンテナの記述で重要な箇所

ports:
  - 8000:5000
  • 5000 という番号がネットワーク内での番号になります。BコンテナのFlaskサーバーのポート番号と同一です。

docker-composeコマンドの実行

2つのコンテナを起動します。

# docker-compose -f docker-compose.dev.yml up -d

まとめ

  • コンテナにアクセスするためのアドレスは、docker-composeファイルのサービス名とポート番号で決まります。
  • コンテナ起動の順序に注意する。
  • サーバーからの応答を待つための時間を設定する。

おわりに

Dockerがアドレスの解決を動のように行っているのか分からず、解決するのに時間がかかりました。

GitHubでソースコードをみることができます。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?