Predefined Dockerfiles¶
Appliku provides a set of predefined Dockerfiles that you can select from the build image dropdown in your application's Build Settings. These templates cover common stacks and can be used as-is or grabbed and customized to fit your project's needs.
For instructions on using custom Dockerfiles, see Deploy from a Dockerfile.
The Dockerfiles below are the current templates for the most used build images. The other build images in each group use the same template with a different Python or Node.js version. See Build Images for the full list.
Trust store step
In October 2026 Mozilla removed three emSign root certificates (emSign Root CA - C1, emSign ECC Root CA - C3 and emSign ECC Root CA - G3) from its trust store. Some base images still trust them. Each template removes them from the system trust store in its first RUN step. Debian-based images disable the three roots. Alpine-based images install the newest ca-certificates-bundle, which is a full update of the trust bundle to the current Mozilla state. An existing application gets this step at its next build. Running containers do not change.
The step changes only the system trust store (/etc/ssl/certs). It does not change certificate stores that come with a tool or library: the Node.js bundled store, the uv bundled roots, certifi (used by pip, requests and httpx) or a Java cacerts file. Update those with the tool or library itself.
Python 3.14 Dockerfile¶
FROM python:3.14.3-trixie
SHELL ["/bin/bash", "-c"]
ENV PIP_NO_CACHE_DIR off
ENV PIP_DISABLE_PIP_VERSION_CHECK on
ENV PYTHONUNBUFFERED 1
ENV PYTHONDONTWRITEBYTECODE 0
# appliku#399: distrust emSign Root CA - C1, emSign ECC Root CA - C3, emSign ECC Root CA - G3 (Mozilla, Oct 2026).
# Remove when the base image ships a ca-certificates package without these roots.
RUN sed -i -E 's#^(mozilla/emSign_(Root_CA_-_C1|ECC_Root_CA_-_C3|ECC_Root_CA_-_G3)\.crt)$#!\1#' /etc/ca-certificates.conf \
&& update-ca-certificates --fresh
RUN apt-get update \
&& apt-get install -y --force-yes \
nano python3-pip gettext chrpath libssl-dev libxft-dev \
libfreetype6 libfreetype6-dev libfontconfig1 libfontconfig1-dev\
&& rm -rf /var/lib/apt/lists/*
RUN pip install --upgrade pip && pip install --upgrade setuptools && pip install gunicorn
WORKDIR /code/
COPY ./code/requirements.txt /code/
RUN pip install -r requirements.txt
COPY ./code/ /code/
COPY ./env/ /env/
RUN source /env/envs_export.sh && if [ -n "$BUILD_COMMAND" ]; then eval $BUILD_COMMAND; fi
RUN source /env/envs_export.sh && if [ -f "manage.py" ]; then if [ "$DISABLE_COLLECTSTATIC" == "1" ]; then echo "collect static disabled"; else echo "Found manage.py, running collectstatic" && python manage.py collectstatic --noinput; fi; else echo "No manage.py found. Skipping collectstatic."; fi;
RUN useradd -ms /bin/bash code
USER code
Python 3.14 + uv Dockerfile¶
FROM python:3.14.3-trixie
SHELL ["/bin/bash", "-c"]
ENV PYTHONUNBUFFERED 1
ENV PYTHONDONTWRITEBYTECODE 0
ENV UV_PROJECT_ENVIRONMENT=/usr/local
ENV UV_LINK_MODE=copy
# appliku#399: distrust emSign Root CA - C1, emSign ECC Root CA - C3, emSign ECC Root CA - G3 (Mozilla, Oct 2026).
# Remove when the base image ships a ca-certificates package without these roots.
RUN sed -i -E 's#^(mozilla/emSign_(Root_CA_-_C1|ECC_Root_CA_-_C3|ECC_Root_CA_-_G3)\.crt)$#!\1#' /etc/ca-certificates.conf \
&& update-ca-certificates --fresh
RUN apt-get update \
&& apt-get install -y --force-yes \
nano gettext chrpath libssl-dev libxft-dev \
libfreetype6 libfreetype6-dev libfontconfig1 libfontconfig1-dev\
&& rm -rf /var/lib/apt/lists/*
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /usr/local/bin/
WORKDIR /code/
COPY ./code/pyproject.tom[l] ./code/uv.loc[k] ./code/requirements.tx[t] /code/
RUN if [ -f "pyproject.toml" ]; then \
UV_PROJECT_ENVIRONMENT=/usr/local uv sync --frozen && \
uv pip install --system gunicorn; \
elif [ -f "requirements.txt" ]; then \
uv pip install --system gunicorn && \
uv pip install --system -r requirements.txt; \
else \
echo "ERROR: No dependency files found. Provide pyproject.toml+uv.lock or requirements.txt." && exit 1; \
fi
ENV UV_NO_SYNC=1
COPY ./code/ /code/
COPY ./env/ /env/
RUN source /env/envs_export.sh && if [ -n "$BUILD_COMMAND" ]; then eval $BUILD_COMMAND; fi
RUN source /env/envs_export.sh && if [ -f "manage.py" ]; then if [ "$DISABLE_COLLECTSTATIC" == "1" ]; then echo "collect static disabled"; else echo "Found manage.py, running collectstatic" && python manage.py collectstatic --noinput; fi; else echo "No manage.py found. Skipping collectstatic."; fi;
RUN useradd -ms /bin/bash code
USER code
Python 3.14 + Node 26 Dockerfile¶
FROM python:3.14.9-trixie
SHELL ["/bin/bash", "-c"]
ENV PIP_NO_CACHE_DIR off
ENV PIP_DISABLE_PIP_VERSION_CHECK on
ENV PYTHONUNBUFFERED 1
ENV PYTHONDONTWRITEBYTECODE 0
# appliku#399: distrust emSign Root CA - C1, emSign ECC Root CA - C3, emSign ECC Root CA - G3 (Mozilla, Oct 2026).
# Remove when the base image ships a ca-certificates package without these roots.
RUN sed -i -E 's#^(mozilla/emSign_(Root_CA_-_C1|ECC_Root_CA_-_C3|ECC_Root_CA_-_G3)\.crt)$#!\1#' /etc/ca-certificates.conf \
&& update-ca-certificates --fresh
RUN apt-get update \
&& apt-get install -y --force-yes \
nano python3-pip gettext chrpath libssl-dev libxft-dev \
libfreetype6 libfreetype6-dev libfontconfig1 libfontconfig1-dev\
&& rm -rf /var/lib/apt/lists/*
ENV NODE_VERSION=26.12.1
ENV NVM_DIR=/usr/local/nvm
RUN apt install -y curl
# Force git to HTTP/1.1 for the nvm git clone below: git over HTTP/2 to GitHub fails on
# the build hosts ("expected flush after ref listing"). Set it with git config so the
# workaround holds regardless of the base image's git version.
RUN git config --global http.version HTTP/1.1
RUN mkdir -p $NVM_DIR && curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.39.7/install.sh | bash
RUN . "$NVM_DIR/nvm.sh" && nvm install ${NODE_VERSION}
RUN . "$NVM_DIR/nvm.sh" && nvm use v${NODE_VERSION}
RUN . "$NVM_DIR/nvm.sh" && nvm alias default v${NODE_VERSION}
ENV PATH="/usr/local/nvm/versions/node/v${NODE_VERSION}/bin/:${PATH}"
RUN node --version
RUN npm --version
RUN npm install --global --allow-scripts=yarn yarn@1.22.22
RUN pip install --upgrade pip && pip install --upgrade setuptools && pip install gunicorn
WORKDIR /code/
COPY ./code/requirements.txt /code/
RUN pip install -r requirements.txt
COPY ./code/ /code/
COPY ./env/ /env/
RUN source /env/envs_export.sh && if [ -n "$BUILD_COMMAND" ]; then eval $BUILD_COMMAND; fi
RUN source /env/envs_export.sh && if [ -f "manage.py" ]; then if [ "$DISABLE_COLLECTSTATIC" == "1" ]; then echo "collect static disabled"; else echo "Found manage.py, running collectstatic" && python manage.py collectstatic --noinput; fi; else echo "No manage.py found. Skipping collectstatic."; fi;
RUN useradd -ms /bin/bash code
USER code
Python 3.14 + uv + Node 26 Dockerfile (default)¶
FROM python:3.14.9-trixie
SHELL ["/bin/bash", "-c"]
ENV PYTHONUNBUFFERED 1
ENV PYTHONDONTWRITEBYTECODE 0
ENV UV_PROJECT_ENVIRONMENT=/usr/local
ENV UV_LINK_MODE=copy
# appliku#399: distrust emSign Root CA - C1, emSign ECC Root CA - C3, emSign ECC Root CA - G3 (Mozilla, Oct 2026).
# Remove when the base image ships a ca-certificates package without these roots.
RUN sed -i -E 's#^(mozilla/emSign_(Root_CA_-_C1|ECC_Root_CA_-_C3|ECC_Root_CA_-_G3)\.crt)$#!\1#' /etc/ca-certificates.conf \
&& update-ca-certificates --fresh
RUN apt-get update \
&& apt-get install -y --force-yes \
nano gettext chrpath libssl-dev libxft-dev \
libfreetype6 libfreetype6-dev libfontconfig1 libfontconfig1-dev\
&& rm -rf /var/lib/apt/lists/*
ENV NODE_VERSION=26.12.1
ENV NVM_DIR=/usr/local/nvm
RUN apt install -y curl
# Force git to HTTP/1.1 for the nvm git clone below: git over HTTP/2 to GitHub fails on
# the build hosts ("expected flush after ref listing"). Set it with git config so the
# workaround holds regardless of the base image's git version.
RUN git config --global http.version HTTP/1.1
RUN mkdir -p $NVM_DIR && curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.39.7/install.sh | bash
RUN . "$NVM_DIR/nvm.sh" && nvm install ${NODE_VERSION}
RUN . "$NVM_DIR/nvm.sh" && nvm use v${NODE_VERSION}
RUN . "$NVM_DIR/nvm.sh" && nvm alias default v${NODE_VERSION}
ENV PATH="/usr/local/nvm/versions/node/v${NODE_VERSION}/bin/:${PATH}"
RUN node --version
RUN npm --version
RUN npm install --global --allow-scripts=yarn yarn@1.22.22
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /usr/local/bin/
WORKDIR /code/
COPY ./code/pyproject.tom[l] ./code/uv.loc[k] ./code/requirements.tx[t] /code/
RUN if [ -f "pyproject.toml" ]; then \
UV_PROJECT_ENVIRONMENT=/usr/local uv sync --frozen && \
uv pip install --system gunicorn; \
elif [ -f "requirements.txt" ]; then \
uv pip install --system gunicorn && \
uv pip install --system -r requirements.txt; \
else \
echo "ERROR: No dependency files found. Provide pyproject.toml+uv.lock or requirements.txt." && exit 1; \
fi
ENV UV_NO_SYNC=1
COPY ./code/ /code/
COPY ./env/ /env/
RUN source /env/envs_export.sh && if [ -n "$BUILD_COMMAND" ]; then eval $BUILD_COMMAND; fi
RUN source /env/envs_export.sh && if [ -f "manage.py" ]; then if [ "$DISABLE_COLLECTSTATIC" == "1" ]; then echo "collect static disabled"; else echo "Found manage.py, running collectstatic" && python manage.py collectstatic --noinput; fi; else echo "No manage.py found. Skipping collectstatic."; fi;
RUN useradd -ms /bin/bash code
USER code
Python 3.11 with Chrome Browser Dockerfile¶
FROM python:3.11-trixie
SHELL ["/bin/bash", "-c"]
ENV PIP_NO_CACHE_DIR off
ENV PIP_DISABLE_PIP_VERSION_CHECK on
ENV PYTHONUNBUFFERED 1
ENV PYTHONDONTWRITEBYTECODE 0
# appliku#399: distrust emSign Root CA - C1, emSign ECC Root CA - C3, emSign ECC Root CA - G3 (Mozilla, Oct 2026).
# Remove when the base image ships a ca-certificates package without these roots.
RUN sed -i -E 's#^(mozilla/emSign_(Root_CA_-_C1|ECC_Root_CA_-_C3|ECC_Root_CA_-_G3)\.crt)$#!\1#' /etc/ca-certificates.conf \
&& update-ca-certificates --fresh
# Installs the current stable Chrome and the chromedriver of the same version.
RUN apt-get update && apt-get install -y wget unzip \
&& wget -q -O /usr/share/keyrings/google-chrome.asc https://dl.google.com/linux/linux_signing_key.pub \
&& echo "deb [arch=amd64 signed-by=/usr/share/keyrings/google-chrome.asc] http://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google-chrome.list \
&& apt-get update && apt-get install -y google-chrome-stable \
&& CHROME_VERSION=$(google-chrome --version | grep -oE '[0-9]+(\.[0-9]+){3}') \
&& cd /tmp \
&& wget -q https://storage.googleapis.com/chrome-for-testing-public/"$CHROME_VERSION"/linux64/chromedriver-linux64.zip \
&& unzip chromedriver-linux64.zip \
&& mv chromedriver-linux64/chromedriver /usr/bin/chromedriver \
&& chmod +x /usr/bin/chromedriver \
&& rm -rf chromedriver-linux64 chromedriver-linux64.zip \
&& rm -rf /var/lib/apt/lists/*
RUN apt-get update \
&& apt-get install -y --force-yes \
nano python3-pip gettext chrpath libssl-dev libxft-dev \
libfreetype6 libfreetype6-dev libfontconfig1 libfontconfig1-dev\
&& rm -rf /var/lib/apt/lists/*
RUN pip install --upgrade pip && pip install --upgrade setuptools && pip install gunicorn
WORKDIR /code/
COPY ./code/requirements.txt /code/
RUN pip install -r requirements.txt
COPY ./code/ /code/
COPY ./env/ /env/
RUN source /env/envs_export.sh && if [ -n "$BUILD_COMMAND" ]; then eval $BUILD_COMMAND; fi
RUN source /env/envs_export.sh && export && if [ -f "manage.py" ]; then if [ "$DISABLE_COLLECTSTATIC" == "1" ]; then echo "collect static disabled"; else echo "Found manage.py, running collectstatic" && python manage.py collectstatic --noinput; fi; else echo "No manage.py found. Skipping collectstatic."; fi;
RUN useradd -ms /bin/bash code
USER code
Node 26 NPM Dockerfile¶
FROM node:26.12.1-alpine
# appliku#399: older Alpine bundles (3.23) still trust the distrusted emSign roots. Get the newest bundle.
RUN apk upgrade --no-cache ca-certificates-bundle
RUN apk add --no-cache libc6-compat build-base python3
WORKDIR /code
COPY code/package*.json ./
RUN npm install
COPY code/. .
COPY ./code/ /code/
COPY ./env/ /env/
RUN source /env/envs_export.sh && if [ -n "$BUILD_COMMAND" ]; then eval $BUILD_COMMAND; fi
USER node
Node 26 Yarn Dockerfile¶
FROM node:26.12.1-alpine
# appliku#399: older Alpine bundles (3.23) still trust the distrusted emSign roots. Get the newest bundle.
RUN apk upgrade --no-cache ca-certificates-bundle
RUN apk add --no-cache libc6-compat build-base python3
# Node 26 images ship no yarn and no corepack. Corepack runs the yarn version from
# package.json "packageManager" (Berry), or yarn 1.x (classic) when the field is absent.
RUN npm install --global corepack && corepack enable
ENV COREPACK_ENABLE_DOWNLOAD_PROMPT=0
WORKDIR /code
COPY code/package.json code/yarn.lock* code/.yarnrc.ym[l] ./
RUN yarn
COPY code/. .
COPY ./code/ /code/
COPY ./env/ /env/
RUN source /env/envs_export.sh && if [ -n "$BUILD_COMMAND" ]; then eval $BUILD_COMMAND; else yarn build; fi
USER node
Node 24 NPM Dockerfile¶
FROM node:24.22.1-alpine
# appliku#399: older Alpine bundles (3.23) still trust the distrusted emSign roots. Get the newest bundle.
RUN apk upgrade --no-cache ca-certificates-bundle
RUN apk add --no-cache libc6-compat build-base python3
WORKDIR /code
COPY code/package*.json ./
RUN npm install
COPY code/. .
COPY ./code/ /code/
COPY ./env/ /env/
RUN source /env/envs_export.sh && if [ -n "$BUILD_COMMAND" ]; then eval $BUILD_COMMAND; fi
USER node
Node 22 NPM Dockerfile¶
FROM node:22.23.4-alpine
# appliku#399: older Alpine bundles (3.23) still trust the distrusted emSign roots. Get the newest bundle.
RUN apk upgrade --no-cache ca-certificates-bundle
RUN apk add --no-cache libc6-compat build-base python3
WORKDIR /code
COPY code/package*.json ./
RUN npm install
COPY code/. .
COPY ./code/ /code/
COPY ./env/ /env/
RUN source /env/envs_export.sh && if [ -n "$BUILD_COMMAND" ]; then eval $BUILD_COMMAND; fi
USER node
Ruby 3.4.1 Dockerfile¶
FROM ruby:3.4.1-slim
SHELL ["/bin/bash", "-c"]
# appliku#399: distrust emSign Root CA - C1, emSign ECC Root CA - C3, emSign ECC Root CA - G3 (Mozilla, Oct 2026).
# Remove when the base image ships a ca-certificates package without these roots.
RUN sed -i -E 's#^(mozilla/emSign_(Root_CA_-_C1|ECC_Root_CA_-_C3|ECC_Root_CA_-_G3)\.crt)$#!\1#' /etc/ca-certificates.conf \
&& update-ca-certificates --fresh
RUN apt-get update && apt-get install -y \
build-essential \
git \
nodejs \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /code/
COPY ./code/Gemfile* /code/
RUN bundle install
COPY ./code/ /code/
COPY ./env/ /env/
RUN source /env/envs_export.sh && if [ -n "$BUILD_COMMAND" ]; then eval $BUILD_COMMAND; fi
Ruby Rails Dockerfile¶
# syntax = docker/dockerfile:1
# Make sure RUBY_VERSION matches the Ruby version in .ruby-version and Gemfile
ARG RUBY_VERSION=3.3.0
FROM registry.docker.com/library/ruby:$RUBY_VERSION-slim as base
SHELL ["/bin/bash", "-c"]
# appliku#399: distrust emSign Root CA - C1, emSign ECC Root CA - C3, emSign ECC Root CA - G3 (Mozilla, Oct 2026).
# Remove when the base image ships a ca-certificates package without these roots.
RUN sed -i -E 's#^(mozilla/emSign_(Root_CA_-_C1|ECC_Root_CA_-_C3|ECC_Root_CA_-_G3)\.crt)$#!\1#' /etc/ca-certificates.conf \
&& update-ca-certificates --fresh
# Rails app lives here
WORKDIR /rails
# Set production environment
ENV RAILS_ENV="production" \
BUNDLE_DEPLOYMENT="1" \
BUNDLE_PATH="/usr/local/bundle" \
BUNDLE_WITHOUT="development"
# Throw-away build stage to reduce size of final image
FROM base as build
# Install packages needed to build gems
RUN apt-get update -qq && \
apt-get install --no-install-recommends -y build-essential git libvips pkg-config libpq-dev curl
# Install application gems
COPY ./code/Gemfile ./code/Gemfile.lock ./
RUN bundle install && \
rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git && \
bundle exec bootsnap precompile --gemfile
RUN gem install pg
# Copy application code
COPY ./code .
COPY ./env/ /env/
ENV SECRET_KEY_BASE_DUMMY=1
# Precompile bootsnap code for faster boot times
RUN source /env/envs_export.sh && bundle exec bootsnap precompile app/ lib/
# Precompiling assets for production without requiring secret RAILS_MASTER_KEY
# RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile
RUN source /env/envs_export.sh && ./bin/rails assets:precompile
# Final stage for app image
FROM base
# Install packages needed for deployment
RUN apt-get update -qq && \
apt-get install --no-install-recommends -y curl libpq-dev libvips && \
rm -rf /var/lib/apt/lists /var/cache/apt/archives
# Copy built artifacts: gems, application
COPY --from=build /usr/local/bundle /usr/local/bundle
COPY --from=build /rails /rails
# Run and own only the runtime files as a non-root user for security
RUN useradd rails --create-home --shell /bin/bash && \
chown -R rails:rails db log storage tmp
USER rails:rails
# Entrypoint prepares the database.
ENTRYPOINT ["/rails/bin/docker-entrypoint"]
# Start the server by default, this can be overwritten at runtime
EXPOSE 3000
CMD ["./bin/rails", "server"]