Files
romm/docker/Dockerfile
Michael Manganiello 98254d50b8 misc: Use nginx templates to allow for environment variable usage
Using the `envsubst` command, we can replace environment variables in
the nginx template files. This allows for more flexibility when
configuring the nginx server.

The Docker image we use as base for Nginx does provide the
`20-envsubst-on-templates.sh` script that will replace environment
variables in the template files.

This change does not include any behavior change, but unblocks future
changes that require environment variables in the nginx configuration.
2025-02-18 22:36:51 -03:00

202 lines
6.2 KiB
Docker

# Stages:
# - frontend-build: Build frontend
# - backend-build: Build backend environment
# - backend-dev-build: Similar to `backend-build`, but also compiles and installs development dependencies
# - rahasher-build: Build RAHasher
# - emulator-stage: Fetch and extract emulators
# - nginx-build: Build nginx modules
# - production-stage: Setup frontend and backend
# - slim-image: Slim image with only the necessary files
# - full-image: Full image with emulator stage
# - dev-slim: Slim image with development dependencies
# - dev-full: Full image with emulator stage and development dependencies
# Versions:
ARG ALPINE_VERSION=3.20
ARG NGINX_VERSION=1.27.1
ARG NODE_VERSION=20.16
ARG PYTHON_VERSION=3.12
FROM node:${NODE_VERSION}-alpine${ALPINE_VERSION} AS frontend-build
WORKDIR /front
COPY ./frontend/package*.json ./
RUN npm ci
COPY ./frontend ./
RUN npm run build
FROM python:${PYTHON_VERSION}-alpine${ALPINE_VERSION} AS backend-build
# git is needed to install streaming-form-data fork
# libffi-dev is needed to fix poetry dependencies for >= v1.8 on arm64
# libpq-dev is needed to build psycopg-c
# mariadb-connector-c-dev is needed to build mariadb-connector
RUN apk add --no-cache \
gcc \
git \
libffi-dev \
libpq-dev \
mariadb-connector-c-dev \
musl-dev
RUN pip install poetry
ENV POETRY_NO_INTERACTION=1 \
POETRY_VIRTUALENVS_IN_PROJECT=1
WORKDIR /src
COPY ./pyproject.toml ./poetry.lock /src/
RUN poetry install --no-ansi --no-cache --only main
FROM backend-build AS backend-dev-build
RUN poetry install --no-ansi --no-cache --all-extras
# TODO: Upgrade Alpine to the same version as the other stages, when RAHasher is updated to work
# with it (seems like Alpine 3.18's g++ v12 is the latest version that works with RAHasher,
# while g++ v13 fails to compile it).
FROM alpine:3.18 AS rahasher-build
RUN apk add --no-cache \
g++ \
git \
linux-headers \
make \
zlib-dev
ARG RALIBRETRO_VERSION=1.8.0
# TODO: Remove `sed` command when RAHasher can be compiled without it.
RUN git clone --recursive --branch "${RALIBRETRO_VERSION}" --depth 1 https://github.com/RetroAchievements/RALibretro.git && \
cd ./RALibretro && \
sed -i '22a #include <ctime>' ./src/Util.h && \
make HAVE_CHD=1 -f ./Makefile.RAHasher
FROM alpine:${ALPINE_VERSION} AS emulator-stage
RUN apk add --no-cache \
7zip \
wget
ARG EMULATORJS_VERSION=4.2.1
RUN wget "https://github.com/EmulatorJS/EmulatorJS/releases/download/v${EMULATORJS_VERSION}/${EMULATORJS_VERSION}.7z" && \
7z x -y "${EMULATORJS_VERSION}.7z" -o/emulatorjs && \
rm -rf "${EMULATORJS_VERSION}.7z";
ARG RUFFLE_VERSION=nightly-2024-12-28
ARG RUFFLE_FILE=ruffle-nightly-2024_12_28-web-selfhosted.zip
RUN wget "https://github.com/ruffle-rs/ruffle/releases/download/${RUFFLE_VERSION}/${RUFFLE_FILE}" && \
unzip -o "${RUFFLE_FILE}" -d /ruffle && \
rm -f "${RUFFLE_FILE}";
FROM alpine:${ALPINE_VERSION} AS nginx-build
RUN apk add --no-cache \
gcc \
git \
libc-dev \
make \
pcre-dev \
zlib-dev
ARG NGINX_VERSION
# The specified commit SHA is the latest commit on the `master` branch at the time of writing.
# It includes a fix to correctly calculate CRC-32 checksums when using upstream subrequests.
# TODO: Move to a tagged release of `mod_zip`, once a version newer than 1.3.0 is released.
ARG NGINX_MOD_ZIP_SHA=8e65b82c82c7890f67a6107271c127e9881b6313
# Clone both nginx and `ngx_http_zip_module` repositories, needed to compile the module from source.
# This is needed to be able to dinamically load it as a module in the final image. `nginx` Docker
# images do not have a simple way to include third-party modules.
RUN git clone https://github.com/evanmiller/mod_zip.git && \
cd ./mod_zip && \
git checkout "${NGINX_MOD_ZIP_SHA}" && \
cd ../ && \
git clone --branch "release-${NGINX_VERSION}" --depth 1 https://github.com/nginx/nginx.git && \
cd ./nginx && \
./auto/configure --with-compat --add-dynamic-module=../mod_zip/ && \
make -f ./objs/Makefile modules && \
chmod 644 ./objs/ngx_http_zip_module.so
FROM nginx:${NGINX_VERSION}-alpine${ALPINE_VERSION} AS production-stage
ARG WEBSERVER_FOLDER=/var/www/html
# Install required packages and dependencies
RUN apk add --no-cache \
bash \
libmagic \
mariadb-connector-c \
libpq \
p7zip \
python3 \
tzdata \
valkey
COPY --from=rahasher-build /RALibretro/bin64/RAHasher /usr/bin/RAHasher
COPY --from=nginx-build ./nginx/objs/ngx_http_zip_module.so /usr/lib/nginx/modules/
COPY --from=frontend-build /front/dist ${WEBSERVER_FOLDER}
COPY ./frontend/assets ${WEBSERVER_FOLDER}/assets
RUN mkdir -p ${WEBSERVER_FOLDER}/assets/romm && \
ln -s /romm/resources ${WEBSERVER_FOLDER}/assets/romm/resources && \
ln -s /romm/assets ${WEBSERVER_FOLDER}/assets/romm/assets
COPY ./backend /backend
# Setup init script and config files
COPY ./docker/init_scripts/* /
COPY ./docker/nginx/js/ /etc/nginx/js/
COPY ./docker/nginx/templates/ /etc/nginx/templates/
COPY ./docker/nginx/default.conf /etc/nginx/nginx.conf
# User permissions
RUN addgroup -g 1000 -S romm && adduser -u 1000 -D -S -G romm romm && \
mkdir /romm /redis-data && chown romm:romm /romm /redis-data
FROM scratch AS slim-image
COPY --from=production-stage / /
COPY --from=backend-build /src/.venv /src/.venv
# Fix virtualenv link to python binary
RUN ln -sf "$(which python)" /src/.venv/bin/python
ENV PATH="/src/.venv/bin:${PATH}"
# Declare the supported volumes
VOLUME ["/romm/resources", "/romm/library", "/romm/assets", "/romm/config", "/redis-data"]
# Expose ports and start
EXPOSE 8080 6379/tcp
WORKDIR /romm
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["/init"]
FROM slim-image AS full-image
ARG WEBSERVER_FOLDER=/var/www/html
COPY --from=emulator-stage /emulatorjs ${WEBSERVER_FOLDER}/assets/emulatorjs
COPY --from=emulator-stage /ruffle ${WEBSERVER_FOLDER}/assets/ruffle
FROM slim-image AS dev-slim
COPY --from=backend-dev-build /src/.venv /src/.venv
# Fix virtualenv link to python binary
RUN ln -sf "$(which python)" /src/.venv/bin/python
FROM full-image AS dev-full
COPY --from=backend-dev-build /src/.venv /src/.venv
# Fix virtualenv link to python binary
RUN ln -sf "$(which python)" /src/.venv/bin/python