Skip to content

Commit

Permalink
build: docker
Browse files Browse the repository at this point in the history
build: docker

build: docker

build: docker

build: docker
  • Loading branch information
subotic committed Feb 22, 2025
1 parent e0eada1 commit e8db218
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 38 deletions.
115 changes: 79 additions & 36 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,57 +1,100 @@
# ---- Build Rust Extension for Multi-Arch ----
FROM rust:latest AS builder

WORKDIR /app

# Install Python 3.13 and pip (needed for maturin)
RUN apt-get update && apt-get install -y python3.11 python3-pip python3-venv gcc musl-tools libssl-dev

# Install maturin for building Rust-Python bindings
RUN cargo install maturin
FROM rust:1.83.0-alpine3.21 AS builder
COPY --from=ghcr.io/astral-sh/uv:0.6.2 /uv /uvx /bin/

RUN \
apk add --no-cache \
build-base \
musl-dev \
gcc \
ca-certificates \
python3 \
python3-dev \
libressl-dev \
pkgconf \
gcompat \
&& rm -rf /var/cache/apk/*

# - Copy from the cache instead of linking since it's a mounted volume,
# - tell uv to byte-compile packages for faster application startups,
# - prevent uv from accidentally downloading isolated Python builds,
# - pick a Python version,
# - and finally declare `/app` as the target for `uv sync` (venv directory).
ENV UV_LINK_MODE=copy \
UV_COMPILE_BYTECODE=1 \
UV_PYTHON_DOWNLOADS=never \
UV_PYTHON=python3.12 \
UV_PROJECT_ENVIRONMENT=/app

# Synchronize DEPENDENCIES without the application itself.
# This layer is cached until uv.lock or pyproject.toml change, which are
# only temporarily mounted into the build container since we don't need
# them in the production one.
# You can create `/app` using `uv venv` in a separate `RUN`
# step to have it cached, but with uv it's so fast, it's not worth
# it, so we let `uv sync` create it for us automagically.
RUN --mount=type=cache,target=/root/.cache \
--mount=type=bind,source=uv.lock,target=uv.lock \
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
uv sync \
--locked \
--no-install-project

# Detect target architecture and set appropriate Rust target
ARG TARGETPLATFORM
RUN echo "Building for platform: $TARGETPLATFORM"

# Copy actual Rust source code
COPY . .
# Copy the rest of the project source code and install it
ADD . /app
WORKDIR /app

# Build the Rust Python package with maturin for the correct architecture
RUN if [ "$TARGETPLATFORM" = "linux/arm64" ]; then \
maturin build --release --out dist --target aarch64-unknown-linux-gnu -i python3.11; \
uv run maturin develop --release --target aarch64-unknown-linux-musl; \
else \
maturin build --release --out dist --target x86_64-unknown-linux-gnu -i python3.11; \
uv run maturin develop --release --target x86_64-unknown-linux-musl; \
fi

RUN ls -la dist
RUN cargo clean

# ---- Setup Python Service ----
FROM python:3.11-slim AS runtime
FROM python:3.12-alpine3.21 AS runtime

WORKDIR /app/ark_resolver
# Install necessary dependencies
RUN apk add --no-cache \
shadow \
libgcc \
libstdc++

# Install required dependencies
RUN apt-get update && apt-get install -y libssl-dev && rm -rf /var/lib/apt/lists/*

# Create a virtual environment
RUN python -m venv /venv
ENV PATH="/venv/bin:$PATH"
# Don't run your app as root.
RUN \
groupadd -r app \
&& useradd -r -d /app -g app -N app

# Install Python dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir --upgrade pip && pip install --no-cache-dir -r requirements.txt
# Copy the pre-built `/app` directory to the runtime container
# and change the ownership to user app and group app in one step.
COPY --from=builder --chown=app:app /app /app

# Copy the Rust-built Python package and install it
COPY --from=builder /app/dist/*.whl .
RUN pip install *.whl && rm -f *.whl

# Verify the installation of the ark_resolver module
RUN python -c "import _rust; print('_rust module installed successfully')"

# Copy Python service code
COPY python/src/ark_resolver /app/ark_resolver
USER app
WORKDIR /app

ENV PYTHONPATH="/app"
# Optional: add the application virtualenv to search path.
# We set the venv in the previous stage to `/app`, so we add it to the PATH.
ENV PATH=/app/bin:$PATH
ENV PYTHONPATH=/app/python/src:/app/lib/python3.12/site-packages
ENV VIRTUAL_ENV=/app

ENTRYPOINT ["python3", "/app/ark_resolver/ark.py"]
CMD ["-s"]
# Verify the installation of the ark_resolver module
# Strictly optional, but I like it for introspection of what I've built
# and run a smoke test that the application can, in fact, be imported.
RUN \
python3 -V \
&& python3 -m site \
&& python3 -c "import sys; print(sys.path)" \
&& python3 -c 'import ark_resolver; print(ark_resolver)' \
&& python3 -c 'import _rust; print(_rust)'

COPY --chmod=0755 entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
CMD ["-s", "-c", "/app/python/src/ark_resolver/ark-config.ini"]
7 changes: 5 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
services:
ark-resolver:
build: .
image: daschswiss/ark-resolver:latest
ports:
- "3336:3336"
environment:
RUST_LOG: info
# ARK_SENTRY_DSN: ""
SENTRY_DEBUG: "True"
ARK_SENTRY_ENVIRONMENT: "local"
ARK_EXTERNAL_HOST: "ark.example.org"
ARK_INTERNAL_HOST: "0.0.0.0"
ARK_INTERNAL_PORT: "3336"
ARK_NAAN: "99999"
ARK_HTTPS_PROXY: false
ARK_REGISTRY: "app/python/src/ark_resolver/ark-registry.ini"
ARK_REGISTRY: "/app/python/src/ark_resolver/ark-registry.ini"
3 changes: 3 additions & 0 deletions entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/sh
set -e # Exit immediately if a command exits with a non-zero status
exec python3 -m ark_resolver.ark "$@"

0 comments on commit e8db218

Please sign in to comment.