Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: CI

on:
push:
branches: [main]
pull_request:

jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Build base stage
uses: docker/build-push-action@v6
with:
context: .
file: docker/Dockerfile
target: base
load: true
tags: elixir-docker-template:base

- name: Build dev stage
uses: docker/build-push-action@v6
with:
context: .
file: docker/Dockerfile
target: dev
load: true
tags: elixir-docker-template:dev

- name: Build prod stage
uses: docker/build-push-action@v6
with:
context: .
file: docker/Dockerfile
target: prod
load: true
tags: elixir-docker-template:prod

- name: Validate compose
run: docker compose config --quiet

- name: Run Hadolint
uses: hadolint/hadolint-action@v3.1.0
with:
dockerfile: docker/Dockerfile
ignore: DL3008
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@
mutagen.yml.lock
2 changes: 2 additions & 0 deletions .hadolint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ignored:
- DL3008
60 changes: 60 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ help to miss some hurdles.

- Docker based environment for Elixir / Erlang
- `justfile` for easier handling of the stack
- Multi-stage Dockerfile for dev and production builds

## Prerequisites

Expand All @@ -28,6 +29,65 @@ You need to have the following installed:
- [Docker](https://docker.io) for running the code
- [Just](https://just.systems) for running commands

## Docker Build

The template uses a single `docker/Dockerfile` with multiple build stages:

| Stage | Purpose |
|-------|---------|
| `base` | Base image with essential tools |
| `dev` | Development environment (default) |
| `prod` | Production build environment |

### Build Commands

```bash
# Development (via compose)
just start

# Production
docker build --target prod -t myapp:prod .
```

The versions are defined in the `FROM` statement in the base stage (currently Elixir 1.19.5, Erlang 28.3, Debian trixie).

### Optimized Production Build

For a smaller production image, you can use a two-stage build pattern. Create a separate `Dockerfile.prod` based on the template's commented sections:

```dockerfile
# Stage 1: Builder
FROM docker.io/hexpm/elixir:1.19.5-erlang-28.3-debian-trixie-20260202-slim AS builder

WORKDIR /app
RUN mix local.hex --force && mix local.rebar --force

COPY mix.exs mix.lock ./
RUN mix deps.get --only prod
RUN mix deps.compile

COPY config/ config/
COPY lib/ lib/
COPY priv/ priv/
RUN mix compile

COPY rel/ rel/
RUN mix release

# Stage 2: Runtime
FROM debian:trixie-20260202-slim

RUN apt-get update && apt-get install -y --no-install-recommends \
libstdc++6 openssl libncurses6 locales ca-certificates \
&& rm -rf /var/lib/apt/lists/*

ENV LANG=en_US.UTF-8
WORKDIR /app

COPY --from=builder /app/_build/prod/rel/your_app ./
CMD ["./bin/server"]
```

## Usage

To use the template either download the files and augment an existing project
Expand Down
6 changes: 3 additions & 3 deletions compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ services:
init: true
build:
context: .
dockerfile: docker/Dockerfile.dev
dockerfile: docker/Dockerfile
target: dev
stdin_open: true
tty: true
volumes:
Expand Down Expand Up @@ -34,9 +35,8 @@ services:
# - default

volumes:
# postgres-data:
# postgres-data:
app:
# The lines below need to be removed when using mutagen
driver: local
driver_opts:
o: bind
Expand Down
92 changes: 92 additions & 0 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# ============================================
# Multi-stage Dockerfile for Elixir development
#
# Build stages:
# --target base : Base image with essential tools
# --target dev : Development environment (default)
# --target prod : Production build environment
#
# Examples:
# docker build --target dev -t myapp:dev .
# docker build --target prod -t myapp:prod .
# ============================================

# ============================================
# Stage 1: Base
# Single source of truth for versions
# ============================================
FROM docker.io/hexpm/elixir:1.19.5-erlang-28.3-debian-trixie-20260202-slim AS base

RUN apt-get update -qq && \
apt-get install -y --no-install-recommends \
build-essential git curl make \
# When using Postgres uncomment the following line
# libpq-dev postgresql-client\
&& rm -rf /var/lib/apt/lists/*

WORKDIR /app

RUN mix local.hex --force && mix local.rebar --force

# ============================================
# Stage 2: Dev
# Development environment with interactive shell
# ============================================
FROM base AS dev

RUN apt-get update -qq && \
apt-get install -y --no-install-recommends \
erlang-crypto inotify-tools \
&& rm -rf /var/lib/apt/lists/*

COPY docker/app/run.sh /run.sh
RUN chmod +x /run.sh

CMD ["/run.sh"]

# ============================================
# Stage 3: Prod
# Production build environment
# ============================================
FROM base AS prod

RUN apt-get update && \
apt-get install -y --no-install-recommends \
libstdc++6 openssl libncurses6 locales ca-certificates \
&& rm -rf /var/lib/apt/lists/*

RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && \
locale-gen

ENV LANG=en_US.UTF-8
ENV LANGUAGE=en_US:en
ENV LC_ALL=en_US.UTF-8
ENV MIX_ENV=prod

# To use for production:
# 1. Uncomment to install dependencies:
# COPY mix.exs mix.lock ./
# RUN mix deps.get --only prod
# RUN mix deps.compile

# 2. Uncomment if your project has a config directory:
# COPY config/config.exs config/prod.exs config/

# 3. Uncomment if your project has assets:
# RUN mix assets.setup
# COPY assets assets
# COPY priv priv
# COPY lib lib

# 4. Uncomment to compile the application:
# RUN mix compile

# 5. Uncomment to build assets for production:
# RUN mix assets.deploy

# 6. Uncomment to build the release:
# COPY rel rel
# RUN mix release

# 7. Update CMD to match your app:
# CMD ["/app/bin/server"]
26 changes: 0 additions & 26 deletions docker/Dockerfile.base

This file was deleted.

33 changes: 0 additions & 33 deletions docker/Dockerfile.dev

This file was deleted.

Loading