Dockerfile Templates
When you deploy a repository that doesn't include a Dockerfile,
GitBlixt auto-generates one based on the files it detects in the repo (e.g. mix.exs
→ Elixir, package.json
→ Node.js).
The same templates are listed below so you can copy or download one as a
starting point for your project — drop it in as Dockerfile
at
the root of your repo and customize as needed.
Detection runs in the order shown below. The first match wins, so for
example a Ruby repo with gem "rails" in its Gemfile gets the
Rails template, not the generic Ruby one.
Elixir / Phoenix
Multi-stage release build on debian-slim.
Detection: mix.exs present
# Auto-generated by GitBlixt for Elixir/Phoenix apps
ARG ELIXIR_VERSION=1.19.5
ARG OTP_VERSION=28.4.1
ARG DEBIAN_VERSION=trixie-20260316-slim
ARG BUILDER_IMAGE="docker.io/hexpm/elixir:${ELIXIR_VERSION}-erlang-${OTP_VERSION}-debian-${DEBIAN_VERSION}"
ARG RUNNER_IMAGE="docker.io/debian:trixie-slim"
# --- deps ---
FROM ${BUILDER_IMAGE} AS deps
RUN apt-get update \
&& apt-get install -y --no-install-recommends build-essential git ca-certificates curl \
&& curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \
&& apt-get install -y --no-install-recommends nodejs \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
RUN mix local.hex --force && mix local.rebar --force
ENV MIX_ENV="prod"
COPY mix.exs mix.lock ./
RUN mix deps.get --only $MIX_ENV
RUN mkdir config
COPY config/config.exs config/${MIX_ENV}.exs config/
RUN mix deps.compile
# --- builder ---
FROM deps AS builder
ENV MIX_ENV="prod"
COPY priv priv
COPY lib lib
RUN mix compile
COPY assets assets
RUN if [ -f assets/package.json ]; then npm install --prefix assets --production; fi
RUN mix assets.deploy 2>/dev/null || true
COPY config/runtime.exs config/
RUN mix release --overwrite
# --- runner ---
FROM ${RUNNER_IMAGE} AS final
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
libstdc++6 openssl libncurses6 locales ca-certificates curl \
&& locale-gen en_US.UTF-8 \
&& rm -rf /var/lib/apt/lists/* \
&& sed -i 's/^tty:x:5:/tty:x:5:nobody/' /etc/group
ENV LANG=en_US.UTF-8
ENV LANGUAGE=en_US:en
ENV LC_ALL=en_US.UTF-8
ENV MIX_ENV="prod"
ENV PHX_SERVER=true
ENV PORT=4000
WORKDIR /app
RUN chown nobody /app
COPY --from=builder --chown=nobody:root /app/_build/prod/rel/ /tmp/rel/
RUN cp -r /tmp/rel/*/* ./ && rm -rf /tmp/rel
USER nobody
EXPOSE ${PORT}
CMD sh -c "if [ -f /app/bin/server ]; then exec /app/bin/server; else exec /app/bin/$(ls /app/bin/ | grep -v '.bat' | head -1) start; fi"
Ruby on Rails
Bundles gems, precompiles assets, runs Puma.
Detection: Gemfile matches /gem\s+['"]rails['"]/
# Auto-generated by GitBlixt for Rails apps
FROM docker.io/ruby:3.3-slim AS base
RUN apt-get update -qq \
&& apt-get install -y --no-install-recommends \
build-essential git libpq-dev curl ca-certificates nodejs npm \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
ENV RAILS_ENV=production
ENV BUNDLE_DEPLOYMENT=true
ENV BUNDLE_WITHOUT=development:test
COPY Gemfile Gemfile.lock* ./
RUN bundle install --jobs 4
COPY . .
# If database.yml is missing (e.g. gitignored), generate one that reads DATABASE_URL
RUN if [ ! -f config/database.yml ]; then \
printf 'production:\n url: <%%= ENV["DATABASE_URL"] %%>\n' > config/database.yml; \
fi
RUN if [ -f bin/rails ]; then \
bundle exec rails assets:precompile 2>/dev/null || true; \
fi
ENV PORT=4000
EXPOSE ${PORT}
CMD bundle exec puma -b tcp://0.0.0.0:${PORT}
Ruby (Sinatra / Rack)
Generic Ruby app — runs config.ru via rackup or app.rb directly.
Detection: Gemfile present
# Auto-generated by GitBlixt for Ruby apps (Sinatra, Rack, etc.)
FROM docker.io/ruby:3.3-slim
RUN apt-get update -qq \
&& apt-get install -y --no-install-recommends \
build-essential git libpq-dev curl ca-certificates \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
ENV BUNDLE_DEPLOYMENT=true
ENV BUNDLE_WITHOUT=development:test
COPY Gemfile Gemfile.lock* ./
RUN bundle install --jobs 4
COPY . .
ENV PORT=4000
EXPOSE ${PORT}
CMD sh -c "if [ -f config.ru ]; then exec bundle exec rackup --host 0.0.0.0 --port ${PORT}; elif [ -f app.rb ]; then exec bundle exec ruby app.rb; else echo 'No config.ru or app.rb found — customize the Dockerfile CMD'; exit 1; fi"
Node.js
Installs dependencies, runs build script if present, starts via npm start.
Detection: package.json present
# Auto-generated by GitBlixt for Node.js apps
FROM docker.io/node:22-slim AS deps
WORKDIR /app
RUN apt-get update \
&& apt-get install -y --no-install-recommends ca-certificates \
&& rm -rf /var/lib/apt/lists/*
COPY package*.json ./
RUN if [ -f package-lock.json ]; then npm ci; else npm install; fi
# --- builder ---
FROM deps AS builder
COPY . .
RUN npm run build --if-present
# --- runner ---
FROM docker.io/node:22-slim AS final
WORKDIR /app
RUN apt-get update \
&& apt-get install -y --no-install-recommends ca-certificates dumb-init \
&& rm -rf /var/lib/apt/lists/*
ENV NODE_ENV=production
ENV PORT=4000
COPY --from=builder /app /app
EXPOSE ${PORT}
CMD ["dumb-init", "npm", "start"]
Python
pip install + gunicorn. Detects Django, Flask-style apps at runtime.
Detection: any of: requirements.txt, pyproject.toml
# Auto-generated by GitBlixt for Python apps
FROM docker.io/python:3.12-slim
WORKDIR /app
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
build-essential libpq-dev curl ca-certificates \
&& rm -rf /var/lib/apt/lists/*
COPY requirements.txt* pyproject.toml* poetry.lock* ./
RUN if [ -f requirements.txt ]; then \
pip install --no-cache-dir -r requirements.txt; \
elif [ -f pyproject.toml ]; then \
pip install --no-cache-dir .; \
fi \
&& pip install --no-cache-dir gunicorn
COPY . .
ENV PORT=4000
ENV PYTHONUNBUFFERED=1
EXPOSE ${PORT}
# Auto-detects Django (manage.py), then falls back to wsgi.py / app.py / main.py.
# ASGI (FastAPI, Starlette) users should replace this with a uvicorn invocation.
CMD sh -c '\
if [ -f manage.py ]; then \
python manage.py migrate --noinput; \
WSGI_DIR=$(find . -maxdepth 3 -name wsgi.py -not -path "./.*" | head -1 | xargs dirname | sed "s|^\./||"); \
exec gunicorn --bind 0.0.0.0:$PORT "${WSGI_DIR}.wsgi:application"; \
elif [ -f wsgi.py ]; then exec gunicorn --bind 0.0.0.0:$PORT wsgi:application; \
elif [ -f app.py ]; then exec gunicorn --bind 0.0.0.0:$PORT app:app; \
elif [ -f main.py ]; then exec gunicorn --bind 0.0.0.0:$PORT main:app; \
else echo "No entry point found (manage.py, wsgi.py, app.py, or main.py)"; exit 1; \
fi'
Go
Multi-stage build with static binary on debian-slim.
Detection: go.mod present
# Auto-generated by GitBlixt for Go apps
FROM docker.io/golang:1.23-bookworm AS builder
WORKDIR /app
COPY go.mod go.sum* ./
RUN go mod download
COPY . .
# If a cmd/ directory exists, build the first command found there;
# otherwise build the package at the repo root.
RUN if [ -d cmd ] && [ -n "$(ls -A cmd 2>/dev/null)" ]; then \
MAIN=$(ls cmd | head -1); \
CGO_ENABLED=0 GOOS=linux go build -o /app/server ./cmd/$MAIN; \
else \
CGO_ENABLED=0 GOOS=linux go build -o /app/server .; \
fi
# --- runner ---
FROM docker.io/debian:trixie-slim AS final
RUN apt-get update \
&& apt-get install -y --no-install-recommends ca-certificates \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY --from=builder /app/server /app/server
ENV PORT=4000
EXPOSE ${PORT}
CMD ["/app/server"]
Static HTML / CSS
Serves files via nginx with SPA-style fallback to index.html.
Detection: index.html present
# Auto-generated by GitBlixt for static HTML/CSS sites
FROM docker.io/nginx:alpine
COPY . /usr/share/nginx/html
RUN printf 'server {\n listen 4000;\n root /usr/share/nginx/html;\n index index.html;\n location / { try_files $uri $uri/ /index.html; }\n}\n' \
> /etc/nginx/conf.d/default.conf
ENV PORT=4000
EXPOSE 4000
CMD ["nginx", "-g", "daemon off;"]
How auto-detection works
On every successful CI pipeline, the deploy worker checks the repository for
a Dockerfile, Dockerfile.build, Dockerfile.prod,
or Dockerfile.production. If one exists, it's used as-is. If
none exist, the templates above are tried in order, and the first whose
detection rule matches the repo is used to build the image.
You can force template generation (ignoring an existing Dockerfile) by
setting an environment's dockerfile_mode to auto.