LoginSignup
1
1

Dockerでコンテナ間通信 (Python)

Last updated at Posted at 2024-02-08

はじめに

Pythonを使用してコンテナ間通信をお試ししたのでそれのメモ。
サーバ(api)に対して、クライアント側からrequestsライブラリでgetし、
実行結果をクライアント側で標準出力させた。

フォルダ構成

clientフォルダとserverフォルダを作成し、それぞれにDockerfileを作成した。
必要なpythonライブラリ類はrequirements.txtを使用せず、直接Dockerfile内でインストールするようにした。

my-app
├─ client
│   ├ client.py
│   └ Dockerfile
├─ server
│   ├ server.py
│   └ Dockerfile
└─ docker-compose.yml

サーバ側(web_server)

FastAPIを参考にserver.pyを実装させていただいた。

server.py
from typing import Union
from fastapi import FastAPI
app = FastAPI()

@app.get("/users/{user_id}/items/{item_id}")
async def read_user_item(
    user_id: int, item_id: str, q: Union[str, None] = None, short: bool = False
):
    item = {"item_id": item_id, "owner_id": user_id}
    if q:
        item.update({"q": q})
    if not short:
        item.update(
            {"description": "This is an amazing item that has a long description"}
        )
    return item

./server/Dockerfileでは必要なライブラリをインストールした後、APIを起動する。

Dockerfile
FROM python:3.9-buster
ENV PYTHONUNBUFFERED=1

WORKDIR /usr/src/app
COPY . ./

RUN pip3 install --upgrade pip
RUN pip3 install fastapi
RUN pip3 install "uvicorn[standard]"

EXPOSE 5000
ENTRYPOINT ["uvicorn", "server:app", "--host", "0.0.0.0", "--port", "5000", "--reload"]

クライアント側(client)

サーバ側(web_server)では5000番ポートを使用するため、そこに対して
getさせるようにした。

client.pyについて、requests.get('http://0.0.0.0:5000/・・のようにIPアドレスを使用したいところであるが、
今回の環境では同一ネットワークに所属するweb_serverに対して名前解決が可能となっているためこちらを使用する。

client.py
import requests

r = requests.get('http://web_server:5000/users/100/items/100?q=100&short=True')
print(r.status_code)
print(r.json())

./client/Dockerfile必要なライブラリをインストールした後、client.pyを起動する。

Dockerfile
FROM python:3.9-buster
ENV PYTHONUNBUFFERED=1

WORKDIR /usr/src/app
COPY . ./

RUN pip3 install --upgrade pip
RUN pip3 install requests

# サーバーを起動
CMD ["python", "client.py"]

docker-compose.yml

web_serverとclientの2つのコンテナを起動する。2つのコンテナは同一ネットワーク(api_network)に所属し、clientの実行はweb_serverの起動に依存させる。

docker-compose.yml
version: '2'
services:
  web_server:
    build: ./server
    container_name: web_server
    tty: true
    # 5000番ポートを使用
    expose:
      - "5000"
    networks:
      - api_network

  client:
    build: ./client
    container_name: client
    networks:
      - api_network
    # web_serverに依存
    depends_on:
      - web_server

networks:
  api_network:

結果

2つのコンテナ起動後、クライアント側のコンテナで実行結果を標準出力できた。

$ docker compose up
web_server  | INFO:     Application startup complete.
web_server  | INFO:     172.19.0.3:40442 - "GET /users/100/items/100?q=100&short=True HTTP/1.1" 200 OK
client      | 200
client      | {'item_id': '100', 'owner_id': 100, 'q': '100'}
client exited with code 0
1
1
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
1
1