我只是在我的基本 CRUD 应用程序中创建一个单阶段 dockerfile。 我想要多阶段,因为减少了我的泊坞窗图像的空间。 Dockerfile
FROM python:3.9-slim
# Set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
# Set the working directory in the container
WORKDIR /app
# Copy the dependencies file to the working directory
COPY requirements.txt .
RUN apt-get update && apt-get install -y default-mysql-client netcat-traditional && rm -rf /var/lib/apt/lists/*
# Install dependencies
RUN pip3 install -r requirements.txt
# Copy the content of the local src directory to the working directory
COPY . .
COPY wait-for.sh .
# Expose port 8000 to the outside world
EXPOSE 8000
RUN chmod +x wait-for.sh
CMD ["uvicorn", "index:app", "--reload", "--host", "0.0.0.0", "--port", "8000"]
所以我在我的 Dockerfile 中执行此操作 Dockerfile.dev
FROM python:3.9-slim as BUILD
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
RUN apt-get update && apt-get install -y default-mysql-client netcat-traditional && rm -rf /var/lib/apt/lists/*
COPY . .
#CMD
FROM python:3.9-slim
COPY --from=BUILD . .
COPY wait-for.sh .
# Expose port 8000 to the outside world
EXPOSE 8000
RUN chmod +x wait-for.sh
CMD ["uvicorn", "index:app", "--reload", "--host", "0.0.0.0", "--port", "8000"]
但是第二步放不下index.py文件。
docker-compose.yml
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile.dev #Here change the Dockerfile and Dockerfile.dev
#Dockerfile for single stage and Dockerfile.dev for multistage
ports:
- 8000:8000
# restart: on-failure
environment:
DATABASE_HOST: db
DATABASE_USER: root
DATABASE_PASSWORD: 12345678
DATABASE_NAME: Student
depends_on:
- db
entrypoint: [ "./wait-for.sh", "db:3306", "--", "uvicorn", "index:app", "--reload", "--host", "0.0.0.0", "--port", "8000" ]
db:
image: mysql:5.7
volumes:
- ./my.cnf:/etc/mysql/my.cnf
environment:
MYSQL_USER: user
MYSQL_ROOT_PASSWORD: 12345678
MYSQL_DATABASE: Student
MYSQL_PASSWORD: 12345678
ports:
- "3307:3306"
我的问题是“是否可以使用多级 docker 来 dockerize 我的 fastapi 应用程序?” 如果可能的话我该怎么做。另外,如果不可能那么为什么我不能这样做。 这个的切入点是什么?
您显示的图像不会受益于多阶段构建。
多阶段构建可以节省空间的设置是,如果您需要一些工具来构建映像,但不需要实际运行容器。对于 Python 应用程序,具有 C 扩展的库需要 C 编译器,该编译器相当大,但仅在安装时才需要。对于这类应用程序,第一阶段可以安装编译器和C头文件,但第二阶段只需要相应的运行时库。
基于 Python 的 Dockerfile 示例可能如下所示。请注意,我们在构建和运行时阶段使用完全相同的基础映像,并且虚拟环境位于同一目录中。第一阶段安装
build-essential
,其中包含完整的C工具链,但相当大;第二阶段不需要那个。
ARG PYTHON=python:3.12-slim
FROM $PYTHON AS build
# Install (large) build-time dependencies
RUN apt-get update \
&& DEBIAN_FRONTEND=noninteractive \
apt-get install --no-install-recommends --assume-yes \
build-essential \
libpq-dev
# Create a virtual environment that can be copied into the next stage
RUN python -m venv /venv
# Install packages into it
WORKDIR /app
COPY requirements.txt ./
RUN /venv/bin/pip install -r requirements.txt
FROM $PYTHON
# Install only the libraries you need to run the application
RUN apt-get update \
&& DEBIAN_FRONTEND=noninteractive \
apt-get install --no-install-recommends --assume-yes \
libpq5
# Copy the virtual environment from the first stage
COPY --from=build /venv/ /venv/
ENV PATH=/venv/bin:$PATH
# The rest of your Dockerfile as before
...
CMD ["uvicorn", ...]
您还询问了入口点的正确值。这在多阶段构建中不会改变,请注意仅使用最终图像的值。
您通常不需要覆盖 Compose 文件中的
entrypoint:
,而且很多情况下也不需要覆盖 command:
。我可能会将对 wait-for.sh
的调用移至 Dockerfile
ENTRYPOINT ["./wait-for.sh", "db:3306", "--"]
CMD ["uvicorn", ...]
更强大的解决方案可能是将其包装在专用的 shell 脚本中,该脚本遵循部署时数据库主机名
#!/bin/sh
# Wait for the database to be ready
if [ -n "$DATABASE_HOST" ]; then
./wait-for.sh "$DATABASE_HOST:3306"
fi
# Switch to the main container command
exec "$@"
此脚本可以是图像的
ENTRYPOINT
(确保使用JSON数组语法),并且您不需要在Compose文件中放置任何特殊内容。