# Dockerfile for ML Weather Application
# Base image: Ubuntu 22.04 LTS
FROM ubuntu:22.04
# Arguments for user and group IDs, typically passed from docker-compose for permission consistency
ARG HOST_UID=1000
ARG HOST_GID=1000
# Set environment variables for non-interactive installs and Python behavior
ENV DEBIAN_FRONTEND=noninteractive \
PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
PYTHONPATH=/app
# Set working directory for the application
WORKDIR /app
# Install Python 3.10, pip, venv, gosu, and clean up apt cache
RUN apt-get update && apt-get install -y --no-install-recommends \
python3 \
python3-pip \
python3-venv \
gosu \
curl \
jq \
&& rm -rf /var/lib/apt/lists/*
# Copy only requirements first to leverage Docker layer caching for dependencies
COPY src/app/requirements.txt .
RUN pip3 install --cache-dir "/root/.cache/pip" -r requirements.txt
# Copy the entire application codebase into the container
COPY src/app/ ./app
# Create an 'appuser' with dynamic UID/GID to avoid permission conflicts with host
# Remove any existing user with the same UID (except 'appuser')
RUN if id -u $HOST_UID >/dev/null 2>&1; then \
existing_user=$(id -nu $HOST_UID); \
if [ "$existing_user" != "appuser" ]; then \
userdel -f "$existing_user" 2>/dev/null || true; \
fi; \
fi
# Create group and user with the specified GID/UID, or rename existing group to 'appuser'
RUN if ! getent group $HOST_GID >/dev/null 2>&1; then \
groupadd -g $HOST_GID appuser; \
else \
existing_group=$(getent group $HOST_GID | cut -d: -f1); \
if [ "$existing_group" != "appuser" ]; then \
groupmod -n appuser "$existing_group"; \
fi; \
fi
RUN if ! id -u appuser >/dev/null 2>&1; then \
useradd -u $HOST_UID -g $HOST_GID -m -s /bin/bash appuser; \
fi
# Ensure correct ownership of the application directory
RUN chown -R appuser:appuser /app
# Copy entrypoint script, make it executable, and set as ENTRYPOINT
COPY fastapi_entrypoint.sh /usr/local/bin/fastapi_entrypoint.sh
RUN chmod +x /usr/local/bin/fastapi_entrypoint.sh
ENTRYPOINT ["/usr/local/bin/fastapi_entrypoint.sh"]
# Do not set USER here; gosu in entrypoint handles user switching
EXPOSE 8000
# Default command executed by the entrypoint script as 'appuser'
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]