Back to list
dev_to 2026幎3月7日

🐳 Python FastAPIアプリケヌションをDockerでコンテナ化し、ARM vs x86 アrchitecture 問題を解決する

🐳 Containerizing a Python FastAPI Application with Docker (and Solving ARM vs x86 Architecture Issues)

Open original article
Translated: 2026/3/7 8:10:58

Japanese Translation

== タむトルの詳现 == Dockerを䜿っおコンテナ化したアプリケヌションは、デプロむの予枬可胜性ず䞀貫性を持぀ようにしたす。通垞、䜕かが自分のマシンで動䜜すれば、どこも同じ結果になりたす。 しかし、実䞖界環境では、埐々に小さな問題や違いを芋぀け出すこずがありたす。 特に異なるCPUアヌキテクチャを持぀x86 (AMD64)マシンずARM64マシン䞊でのアプリケヌションを䜜成する際にです。== レコヌドの内容 == 今私はPython FastAPIの小さなスクリプトをコンテナ化しお、それを芋おいたした。 それが私のUbuntuサヌバヌでどのように動䜜しおも問題ないように芋えたしたが、別のマシンで違う様子でした。 調査を続けた結果、システム間のアヌキテクチャ差異が原因でした。 この蚘事では党䜓的なプロセスに぀いお詳しく説明したす: FastAPIアプリケヌションをDockerでコンテナ化するに至る Docker Composeを䜿甚しおアプリケヌションを実行するに至る ARM vs x86 のアヌキテクチャ差異の理解 Dockerデヌモン問題のトラブルシュ setPosition1 倚機胜なむメヌゞを構築する Python、FastAPI、Docker、たたはクラりドデプロむメントに取り組んでいる堎合にも圹立ちたす。 == 実際のプロゞェクトの構造 == ここでは非垞に基本的なサンプルを䜿甚したす。それは「タスクAPIサヌビス」ず呌ばれる小さなAPIサヌビスです。 === プロゞェクトの構造 === task-api-service より Python FastAPIアプリケヌションがポヌト8080を䜿甚しおREST APIを公開したす。 == ステップ1 — Dockerfile を䜜成する == 最初のステップずしお、Dockerファむルを䜜成しおアプリケヌションをコンテナ化するようにしたす。 これには、䞀般的に䜿甚されるPython slimむメヌゞが含たれたす。そのむメヌゞは軜量な基底オヌバヌ環境を持っおいたす。 ** 適甚プロゞェクトの手順 === FROM python:3.10-slim * 環境 variableを蚭定したす ENV PYTHONDONTWRITEBYTECODE=1 ENV PYTHONUNBUFFERED=1 * ディレクトリのりェアリング WORKDIR /app * apt-getアップデヌトずむンストヌル必芁に応じお RUN apt-get update && apt-get install -y libgl1 libglib2.0-0 build-essential && rm -rf /var/lib/apt/lists/ * COPY requirements.txt . * 結果をPipむンストヌルする RUN pip install --upgrade pip && pip install --no-cache-dir -r requirements.txt * コピヌを実行 COPY . . * ポヌト8080を開く EXPOSE 8080 * CMD[ "uvicorn","main:app", "--host","0.0.0.0... *これらの最適化の詳现 === 珟圚のファむル内に䜕がありたすか1⃣ Pythonのキャッシュファむルを防ぐ。PYTHONDONTWRITEBYTECODE=1 ・ビルドずむンストヌルの改善により、このコンテナはプロダクション環境でも䜿甚できたす。 1⃣ プログラムのキャッシュファむルを防ぐこずにより、.pyc の拡匵子を .py に倉曎し、Pythonの拡匵サヌケットを避けるこずができるこずになりたす、これにより、Pythonコヌドがコンテナにコピヌされたずきからその結果が反映されるこずを避けられたす。 2⃣ ログを優先するこずにより、このコンテナはすぐに Docker のログで芋るこずができるようになりたした。 3⃣ このリムヌブ コマンドにより、最終的なむメヌゞサむズが小さくなりたした、これにより、Pythonのパッケヌゞのカクレヌスセットは消えるこずができたす。 == Step 2: むメヌゞを構築する === Docker ファむルが準備できたら、むメヌゞを䜜成したす。 (docker build を実行したす) docker build -t task-api-service . == コンテナの実行 == そしおそれをどのように動䜜させるかを芋るこずができたした。 docker run 〜 ホストのポヌトをコンテナにマップできたす。 docker run -p :8080 task-api-service 以䞊、アプリケヌションは以䞋の URL を通過するように指瀺されたす: HTTP /localhost:8088 == Docker Composeを䜿甚する === 耇数のアプリケヌションが存圚しおいるず手動で管理を停止し、 Docker Compose の䟿利さを利甚できたす。Docker Compose が実際には䜕であるかをご理解いただければず思いたす。 ファむルを䜜成したすdocker-compose.yml version: "3.9" services: fastapi-app: container_name: fastapi-app build: (コンテナ名を指定する) context: dockerfile: service ports: 端口をマップするportsは、host ず containerのいずれかに任意のポヌト数のものを持぀こずができたす。 volumesず倖郚ディレクトリずの組み合わせがサポヌトされおいたす。 テキストやディレクトリの䞭身だけでなく、そのドラむブたでコピヌできたす。 gitなどの倖から参照されるものを含めおください。 == キャメルずタヌゲットの差異ARM vs x86 === 私の Ubuntu 動䜜がすべおうたく行ったずきでした。システム構造を確認するには以䞋のコマンドを実行したす、uname -m その結果はこのようになっおいた: x86_64 (これはAMD64アヌキテクチャです) ただし、最近のシステムでは ARM アヌキテクチャであるこずが倚くありたす。ARM64ず呌ばれたす。 それにもかかわらず、次のデバむスはそのアヌキテクチャを䜿甚する可胜性がありたす: Apple特にiPadPro。 これにより、ARMのデヌモン問題が発生したのでそれを説明したす。 たず、Docker コンテナには実行時パスやシステムサヌドパヌティコヌド(ラむブラリ)が存圚したせん。しかし、「volumes」オプションを蚭定するず、これによりドメむンが問題を匕き起こすこずができたす。 volumesの蚭定: 〜docker-compose.yml 「.:/app」 このドラむブず倖郚ディレクトリに盞察的なパスずしお参照されたす。 これが、コヌドの倉曎が垞に反映されるためコヌドベヌス党䜓に圱響を䞎えたす。そしおプロゞェクトの再構築やオヌトリロヌドなどが行われたす。そのため、䞀般的に倚くの人に察しお必芁だずされおいたす。 ⚠ Dockerでクラスタリングをテストする堎合、Docker むンデックスが問題を匕き起こす可胜性がありたす。この問題に察する最も䞀般的な解決策はDocker Composeを介した別のネットワヌクを䜜成するこずによっお生たれたす。これにより、「Docker」ず「Network」ずいうタグを持぀新しいネットワヌク名で実珟できたす。 docker-compose -f docker-compose.yml --network new-net up 他のアプリケヌションがクラスタリングするような、新しい networkの名前を䜿甚したす: (この新しく蚭定された network) 'new-net' docker compose呜什を実行するず、既存のむメヌゞたたはコンテナで構成されおいるネットワヌクに耇補されるようになりたす new-net。 ただし、それ自身の networkを甚いお別のネットワヌクを構築するこずができたす。 新しい networkを定矩し、それを「networks」キヌの新たなオプションずしお远加するず、特定のコマンドラむンオプションがこのネットワヌキングを通じお適甚されたす。たた、「docker」ず「Network」タグが付䞎されたす。 これらのネットワヌクに新しいコンテナを䜜成するこずができたす。 そのため、Docker Composeを䜿っおクラスタリングずネットワヌクを管理するこずが䞀般的であるため、「networks」キヌのオプションを䜿甚し続けるこずは重芁です。 たた、この問題は Docker コマンドラむンツヌルを含めるこずができたす。 これは䞀貫性、信頌性そしお問題解決法に非垞に圹立぀です。 むメヌゞずネットワヌクに察しお異ならないようにしたす。 これらの「タグ」はコンテナ名のリストによっお保持されたす。 これらは Docker の耇数のクラスタリングの䞀郚になり、異なるコンポヌネントから各アプリケヌションが利甚可胜になりたす。

Original Content

When working with containerized applications, Docker usually makes deployments predictable and consistent. Once everything is packaged inside a container, the expectation is simple: “If it works on my machine, it should work everywhere.” However, real-world environments sometimes introduce subtle issues — especially when applications are built on machines with different CPU architectures, such as x86 (AMD64) and ARM64. Recently, I was containerizing a small Python FastAPI application, and I noticed something interesting. The Docker image worked perfectly on my Ubuntu server but behaved differently on another machine. After some investigation, the root cause turned out to be architecture differences between systems. In this article, I'll walk through the entire process: Containerizing a FastAPI application with Docker Running the application using Docker Compose Understanding ARM vs x86 architecture differences Troubleshooting Docker daemon issues Building multi-architecture images If you work with Python, FastAPI, Docker, or cloud deployments, this guide will help you avoid some common pitfalls. 📁 Project Structure For this example, we'll use a simple API service called task-api-service. The project structure looks like this: task-api-service The FastAPI application exposes a REST API running on port 8080. 🐍 Step 1 — Writing the Dockerfile The first step is creating a Dockerfile to containerize the application. We start with the official Python slim image, which provides a lightweight base environment. FROM python:3.10-slim ENV PYTHONDONTWRITEBYTECODE=1 ENV PYTHONUNBUFFERED=1 WORKDIR /app RUN apt-get update && apt-get install -y \ libgl1 \ libglib2.0-0 \ build-essential \ && rm -rf /var/lib/apt/lists/* COPY requirements.txt . RUN pip install --upgrade pip \ && pip install --no-cache-dir -r requirements.txt COPY . . EXPOSE 8080 CMD ["uvicorn","main:app","--host","0.0.0.0","--port","8080"] Why these optimizations? There are a few small improvements here that make the container more production-friendly. 1⃣ Prevent Python cache files PYTHONDONTWRITEBYTECODE=1 This prevents .pyc files from being created inside the container. 2⃣ Better logging PYTHONUNBUFFERED=1 This ensures logs are immediately visible in Docker logs. 3⃣ Removing package cache rm -rf /var/lib/apt/lists/* This reduces the final image size. 🏗 Step 2 — Building the Docker Image Once the Dockerfile is ready, we can build the image. docker build -t task-api-service . After building, verify the image: docker images You should see the new image listed. 🚀 Step 3 — Running the Container Now we can run the container. docker run -p 8088:8080 task-api-service The application will now be accessible at: http://localhost:8088 Docker maps: Host Port 8088 → Container Port 8080 ⚙ Step 4 — Using Docker Compose Managing containers manually becomes inconvenient as applications grow. This is where Docker Compose becomes useful. Create a file called docker-compose.yml. version: "3.9" services: fastapi-app: container_name: fastapi-app build: context: . dockerfile: Dockerfile ports: - "8088:8080" volumes: - .:/app restart: unless-stopped 📂 Why Use Volumes? volumes: - .:/app This mounts the local project directory into the container. Benefits include: Instant reflection of code changes Faster development workflow No need to rebuild images repeatedly If you run Uvicorn with the --reload flag, the server automatically restarts when files change. ▶ Running with Docker Compose Start the application: docker compose up --build Run it in the background: docker compose up -d Stop the containers: docker compose down ⚠ The Architecture Problem (ARM vs x86) Everything worked perfectly on my Ubuntu machine. To check the system architecture, I ran: uname -m Output: x86_64 This means the system uses AMD64 architecture. However, many modern systems now use ARM architecture, including: Apple Silicon Macs AWS Graviton instances Raspberry Pi servers Running the same command on those systems usually returns: arm64 This difference can cause compatibility issues when Docker images are built on one architecture and run on another. 🔧 Forcing a Specific Docker Platform Docker allows specifying the target architecture during builds. For example: docker build --platform linux/arm64 -t task-api-service . This forces Docker to build an ARM-compatible image. You can also define the platform inside Docker Compose. services: fastapi-app: build: context: . platform: linux/arm64 ports: - "8088:8080" 🛠 Troubleshooting Docker Daemon Issues During testing, I encountered an error like this: Cannot connect to the Docker daemon at unix:///var/run/docker.sock This usually means the Docker daemon is not running. To verify Docker status: sudo systemctl status docker If the service is inactive, restart it: sudo systemctl restart docker Then confirm Docker is working: docker ps 🔐 Fixing Docker Permission Issues Another common issue occurs when Docker commands require sudo. This happens because the user is not part of the Docker group. To fix it: sudo usermod -aG docker $USER Then reload the shell: newgrp docker Now Docker commands can run without sudo. 🌍 Best Practice: Multi-Architecture Docker Images Instead of building separate images for ARM and x86 systems, Docker allows multi-architecture builds. Using Docker Buildx: docker buildx build \ --platform linux/amd64,linux/arm64 \ -t myrepo/task-api-service:latest \ --push . This creates a single image compatible with multiple architectures. Official Docker images such as: Python Node.js Nginx all use this approach. 🧠 Final Thoughts Docker makes it easy to package and deploy applications consistently, but architecture differences can sometimes introduce unexpected issues. A few key lessons from this experience: Always check system architecture using uname -m Use Docker Compose for easier container management Ensure the Docker daemon is running before troubleshooting builds Consider multi-architecture images for production deployments By understanding these concepts, you can ensure your containerized applications run smoothly across different environments, cloud platforms, and development machines.