-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDockerfile
More file actions
111 lines (87 loc) · 3.79 KB
/
Copy pathDockerfile
File metadata and controls
111 lines (87 loc) · 3.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# syntax=docker/dockerfile:1
# Code ships as an OTP release: the builder produces a self-contained tree
# with its own ERTS, so the runtime image needs no Erlang or Elixir installed.
ARG ELIXIR_VERSION=1.20.3
ARG OTP_VERSION=29.0.5
ARG DEBIAN_VERSION=bookworm-20260803-slim
ARG BUILDER_IMAGE="hexpm/elixir:${ELIXIR_VERSION}-erlang-${OTP_VERSION}-debian-${DEBIAN_VERSION}"
ARG RUNNER_IMAGE="debian:${DEBIAN_VERSION}"
FROM ${BUILDER_IMAGE} AS builder
# build-essential is for MuonTrap's port binary, which is C.
# protobuf-compiler is `protoc`, which prost-build shells out to when
# compiling the WAL schema for the Rustler NIF under `native/code_native/`.
# curl is only here to fetch rustup; it is apt-removed afterwards.
RUN apt-get update -y \
&& apt-get install -y --no-install-recommends \
build-essential \
git \
ca-certificates \
curl \
protobuf-compiler \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
# Debian bookworm ships cargo 1.65, which cannot read a Cargo.lock written by
# the toolchain we pin in `mise.toml`. Install Rust via rustup at the same
# version so the lock file stays reproducible across machines.
ENV RUSTUP_HOME=/opt/rustup CARGO_HOME=/opt/cargo PATH=/opt/cargo/bin:$PATH
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \
| sh -s -- -y --default-toolchain 1.97.0 --profile minimal --no-modify-path \
&& rustc --version && cargo --version
WORKDIR /app
RUN mix local.hex --force && mix local.rebar --force
ENV MIX_ENV="prod"
# Dependencies first, so editing application code does not invalidate them.
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
# priv/ carries the proto schema the NIF compiles against, and native/ is the
# crate itself. Both have to be in place before `mix compile`, because the
# Rustler build step runs there.
COPY priv priv
COPY native native
COPY lib lib
RUN mix compile
COPY config/runtime.exs config/
COPY rel rel
RUN mix release
# ----------------------------------------------------------------------------
FROM ${RUNNER_IMAGE}
# git is the actual workhorse: Code does not reimplement it.
# curl is used by the pre-receive hook to call back into the node.
# libncurses and locales are what the ERTS expects to find.
RUN apt-get update -y \
&& apt-get install -y --no-install-recommends \
git \
curl \
ca-certificates \
libstdc++6 \
openssl \
libncurses6 \
locales \
&& apt-get clean && 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 LANGUAGE=en_US:en LC_ALL=en_US.UTF-8
# Git needs a writable HOME even though every invocation disables user config.
ENV HOME=/app
WORKDIR /app
RUN groupadd --system --gid 1000 code \
&& useradd --system --uid 1000 --gid code --home /app code \
&& mkdir -p /var/lib/code/repositories \
&& chown -R code:code /app /var/lib/code
COPY --from=builder --chown=code:code /app/_build/prod/rel/code ./
USER code
# The port-table ceiling is deliberately not set here. rel/env.sh.eex derives
# ERL_MAX_PORTS from CODE_MAX_PORTS (default 65536) every time the release
# starts; baking ERL_MAX_PORTS into the image made CODE_MAX_PORTS ineffective.
ENV CODE_DATA_DIR=/var/lib/code/repositories \
CODE_GIT_PORT=4000 \
CODE_HOOK_PORT=4001 \
CODE_ADMIN_PORT=4002
# 4000 git + mcp (public), 4002 admin + metrics (internal).
# 4001 is the hook callback and binds to loopback, so it is deliberately absent.
EXPOSE 4000 4002
# The release's own health check, so the image is useful without an orchestrator.
HEALTHCHECK --interval=15s --timeout=5s --start-period=20s --retries=3 \
CMD curl -fsS "http://127.0.0.1:${CODE_ADMIN_PORT}/health" || exit 1
CMD ["/app/bin/code", "start"]