はじめに
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を実装させていただいた。
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を起動する。
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に対して名前解決が可能となっているためこちらを使用する。
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を起動する。
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の起動に依存させる。
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