-
Notifications
You must be signed in to change notification settings - Fork 2
/
Dockerfile
143 lines (133 loc) · 5.57 KB
/
Dockerfile
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
FROM alpine:3.17.3
# Important! Update this no-op ENV variable when this Dockerfile
# is updated with the current date. It will force refresh of all
# of the base images and things like `apt-get update` won't be using
# old cached versions when the Dockerfile is built.
ENV REFRESHED_AT=2023-04-04
ENV LANG=en_US.UTF-8 \
HOME=/opt/app/ \
# Set this so that CTRL+G works properly
TERM=xterm \
OTP_VERSION=25.3 \
OTP_DOWNLOAD_SHA256=85c447efc1746740df4089d75bc0e47b88d5161d7c44e9fc4c20fa33ea5d19d7
WORKDIR /tmp/erlang-build
# Update Alpine base libs
RUN set -xe && \
# Add edge repos tagged so that we can selectively install edge packages
echo "@edge http://dl-cdn.alpinelinux.org/alpine/edge/main" >> /etc/apk/repositories && \
# Upgrade Alpine and base packages
apk add --no-cache --update apk-tools musl ca-certificates tini
# Install Erlang
RUN set -xe && \
OTP_DOWNLOAD_URL="https://github.com/erlang/otp/archive/OTP-${OTP_VERSION}.tar.gz" && \
# Create default user and home directory, set owner to default
mkdir -p ${HOME} && \
adduser -s /bin/sh -u 1001 -G root -h ${HOME} -S -D default && \
chown -R 1001:0 ${HOME} && \
# Install fetch deps
apk add --no-cache --update --virtual .fetch-deps curl && \
# Install Erlang/OTP build deps
apk add --no-cache --update --virtual .build-deps \
build-base \
dpkg-dev dpkg \
gcc g++ libc-dev \
linux-headers \
make \
autoconf \
ncurses-dev \
openssl-dev \
unixodbc-dev \
lksctp-tools-dev \
tar \
pcre \
zlib-dev && \
# Download Erlang/OTP
curl -fSL -o otp-src.tar.gz "${OTP_DOWNLOAD_URL}" && \
echo "$OTP_DOWNLOAD_SHA256 otp-src.tar.gz" | sha256sum -c - && \
export ERL_TOP="/usr/src/otp_src_${OTP_VERSION%%@*}" && \
mkdir -vp $ERL_TOP && \
# Note: if your x86_64 host fails to untar during multiarch build run:
#
# docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
#
tar -xzf otp-src.tar.gz -C $ERL_TOP --strip-components=1 && \
rm otp-src.tar.gz && \
( cd $ERL_TOP && \
export gnuBuildArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)" && \
export gnuArch="$(dpkg-architecture --query DEB_HOST_GNU_TYPE)" && \
./otp_build autoconf && \
./configure \
--build="$gnuBuildArch" \
--host="$gnuArch" \
--prefix=/usr/local \
--sysconfdir=/etc \
--mandir=/usr/share/man \
--infodir=/usr/share/info \
--without-javac \
--without-jinterface \
--without-wx \
--without-debugger \
--without-observer \
--without-cosEvent \
--without-cosEventDomain \
--without-cosFileTransfer \
--without-cosNotification \
--without-cosProperty \
--without-cosTime \
--without-cosTransactions \
--without-et \
--without-gs \
--without-ic \
--without-megaco \
--without-orber \
--without-percept \
--without-odbc \
--enable-kernel-poll \
--enable-threads \
--enable-shared-zlib \
--enable-dynamic-ssl-lib \
--enable-ssl=dynamic-ssl-lib \
--enable-sctp && \
make -j$(getconf _NPROCESSORS_ONLN) && \
make install ) && \
find /usr/local -regex '/usr/local/lib/erlang/\(lib/\|erts-\).*/\(man\|doc\|obj\|c_src\|emacs\|info\|examples\)' | xargs rm -rf && \
(find /usr/local -name src | xargs -r find | grep -v '\.hrl$' | xargs rm -v || true) && \
(find /usr/local -name src | xargs -r find | xargs rmdir -vp || true) && \
rm -rf /usr/local/lib/erlang/lib/*test* \
/usr/local/lib/erlang/usr \
/usr/local/lib/erlang/misc \
/usr/local/lib/erlang/erts*/lib/lib*.a \
/usr/local/lib/erlang/erts*/lib/internal && \
scanelf --nobanner -E ET_EXEC -BF '%F' --recursive /usr/local | xargs -r strip --strip-all && \
scanelf --nobanner -E ET_DYN -BF '%F' --recursive /usr/local | xargs -r strip --strip-unneeded && \
runDeps="$( \
scanelf --needed --nobanner --format '%n#p' --recursive /usr/local \
| tr ',' '\n' \
| sort -u \
| awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \
)" && \
apk add --virtual .erlang-rundeps $runDeps lksctp-tools ca-certificates && \
apk del .fetch-deps .build-deps && \
rm -rf /var/cache/apk/* && \
rm -rf $ERL_TOP && \
rm -rf /tmp/erlang-build
RUN (erl -eval "beam_lib:strip_release('/usr/local/lib/erlang/lib')" -s init stop > /dev/null) && \
(/usr/bin/strip /usr/local/lib/erlang/erts-*/bin/* || true)
# Update CA certificates
RUN update-ca-certificates --fresh
WORKDIR ${HOME}
# This is critical when you run this container in Google Kubernetes engine or similar engines where
# running process would get a PID 1.
#
# BEAM is usually not started by itself but via some shell script (eg. the one generated by
# Elixir 1.9 releases or Distillery) and this script is not designed to become an init script
# for a Docker container and it DOES NOT releases does not reap zombie processes.
# So whenever a child process runs and terminates inside the same container it would result in memory and
# PID leak to a point where host VM would get unresponsive.
#
# A good example why you would start a process within container is the `ping` command for liveness probes.
# It starts a VM to issue an RPC command to a live node and then terminates, but would never be reaped.
#
# Tini would become an entrypoin script and would take care of zombie reaping no matter how you start the VM.
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["erl"]