Skip to content

Commit 23d17e2

Browse files
authored
Merge pull request #71 from luislavena/add-crystal-1.8
Builds Crystal 1.18.2
2 parents 41a292d + e74c3b2 commit 23d17e2

File tree

2 files changed

+303
-0
lines changed

2 files changed

+303
-0
lines changed

.github/versions.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
{
22
"1.17": {
33
"crystal_full": "1.17.0"
4+
},
5+
"1.18": {
6+
"crystal_full": "1.18.2"
47
}
58
}

docker/1.18/Dockerfile

Lines changed: 300 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,300 @@
1+
# syntax=docker/dockerfile:1
2+
3+
# ---
4+
# Stages:
5+
#
6+
# stage0: use build platform and existing compiler to cross-compile for target
7+
# stage1: link cross-compiled objects into executables on the target platform
8+
# stage2: prepare directory structure, source code and final executables
9+
# stage3: copy over artifacts and development utilities and dependencies
10+
11+
# ---
12+
# stage0: bootstrap Crystal using Alpine's build of Crystal
13+
ARG ALPINE_VERSION=3.23.2
14+
FROM --platform=$BUILDPLATFORM alpine:${ALPINE_VERSION} AS stage0
15+
16+
# expose the target architecture to be used in cross-compilation
17+
ARG TARGETARCH
18+
19+
# install dependencies needed for cross-compilation of Crystal and Shards
20+
RUN --mount=type=cache,sharing=private,target=/var/cache/apk \
21+
set -eux; \
22+
apk add \
23+
crystal \
24+
curl \
25+
g++ \
26+
git \
27+
llvm21-dev \
28+
make \
29+
shards \
30+
yaml-dev \
31+
;
32+
33+
# download and compile Crystal source for target platform
34+
RUN set -eux -o pipefail; \
35+
cd /tmp; \
36+
export \
37+
CRYSTAL_VERSION=1.18.2 \
38+
CRYSTAL_SHA256=f2cd4b20f649ef716fcfa758972f36bb35f2f67e13991e3055226a0d101c19ca \
39+
; \
40+
{ \
41+
curl --fail -Lo crystal.tar.gz https://github.com/crystal-lang/crystal/archive/refs/tags/${CRYSTAL_VERSION}.tar.gz; \
42+
echo "${CRYSTAL_SHA256} *crystal.tar.gz" | sha256sum -c - >/dev/null 2>&1; \
43+
tar -xf crystal.tar.gz; \
44+
rm crystal.tar.gz; \
45+
mv crystal-${CRYSTAL_VERSION} crystal; \
46+
}; \
47+
{ \
48+
cd /tmp/crystal; \
49+
# prepare man page
50+
gzip -9 man/crystal.1; \
51+
mkdir -p /usr/local/share/man/man1; \
52+
cp -f man/*.1.gz /usr/local/share/man/man1/; \
53+
# build Compiler for target architecture
54+
mkdir -p .build; \
55+
make crystal release=1 static=1 target=$TARGETARCH-alpine-linux-musl | tail -1 | tee .build/crystal.sh; \
56+
rm -rf src/llvm/ext/llvm_ext.o; \
57+
}
58+
59+
# download and compile Shards source for target platform
60+
RUN set -eux -o pipefail; \
61+
cd /tmp; \
62+
export \
63+
SHARDS_VERSION=0.19.1 \
64+
SHARDS_SHA256=2a49e7ffa4025e0b3e8774620fa8dbc227d3d1e476211fefa2e8166dcabf82b5 \
65+
; \
66+
{ \
67+
curl --fail -Lo shards.tar.gz https://github.com/crystal-lang/shards/archive/refs/tags/v${SHARDS_VERSION}.tar.gz; \
68+
echo "${SHARDS_SHA256} *shards.tar.gz" | sha256sum -c - >/dev/null 2>&1; \
69+
tar -xf shards.tar.gz; \
70+
rm shards.tar.gz; \
71+
mv shards-${SHARDS_VERSION} shards; \
72+
}; \
73+
{ \
74+
cd /tmp/shards; \
75+
# prepare man pages
76+
gzip -9 man/shards.1 man/shard.yml.5; \
77+
mkdir -p /usr/local/share/man/man1 /usr/local/share/man/man5; \
78+
cp -f man/*.1.gz /usr/local/share/man/man1/; \
79+
cp -f man/*.5.gz /usr/local/share/man/man5/; \
80+
# build for target platform
81+
make bin/shards release=1 static=1 FLAGS="--cross-compile --target $TARGETARCH-alpine-linux-musl" | tail -1 | tee bin/shards.sh; \
82+
}
83+
84+
# ---
85+
# stage1: link compiled objects on target platform
86+
FROM alpine:${ALPINE_VERSION} AS stage1
87+
88+
# install dependencies needed for linking
89+
RUN --mount=type=cache,sharing=private,target=/var/cache/apk \
90+
set -eux; \
91+
apk add \
92+
g++ \
93+
gc-static \
94+
gcc \
95+
git \
96+
libxml2-static \
97+
llvm21-dev \
98+
llvm21-static \
99+
make \
100+
musl-dev \
101+
pcre2-static \
102+
yaml-static \
103+
zlib-static \
104+
zstd-static \
105+
;
106+
107+
# copy build artifacts from stage0
108+
COPY --from=stage0 /tmp/crystal/.build /tmp/crystal/.build
109+
COPY --from=stage0 /tmp/crystal/Makefile /tmp/crystal/Makefile
110+
COPY --from=stage0 /tmp/crystal/src/llvm/ext /tmp/crystal/src/llvm/ext
111+
COPY --from=stage0 /tmp/shards/bin /tmp/shards/bin
112+
113+
# link objects to final binaries
114+
RUN set -eux; \
115+
# compile LLVM extension and link the compiler
116+
{ \
117+
cd /tmp/crystal; \
118+
mkdir -p spec/; \
119+
make llvm_ext; \
120+
sh -ex .build/crystal.sh; \
121+
# smoke test
122+
.build/crystal --version; \
123+
# copy final binary
124+
mkdir -p /tmp/usr/local/bin; \
125+
cp -f .build/crystal /tmp/usr/local/bin/; \
126+
}; \
127+
# compile shards
128+
{ \
129+
cd /tmp/shards; \
130+
sh -ex bin/shards.sh; \
131+
# smoke test
132+
bin/shards --version; \
133+
# copy final binary
134+
mkdir -p /tmp/usr/local/bin; \
135+
cp -f bin/shards /tmp/usr/local/bin/; \
136+
}
137+
138+
# ---
139+
# stage2: prepare binaries and code for final image
140+
FROM alpine:${ALPINE_VERSION} AS stage2
141+
142+
# combine source code and final binaries from previous stages
143+
COPY --from=stage0 /tmp/crystal/src /usr/local/share/crystal/src
144+
COPY --from=stage0 /usr/local/share/man /usr/local/share/man
145+
COPY --from=stage1 /tmp/usr/local/bin /usr/local/bin
146+
147+
# ---
148+
# stage3: final image
149+
FROM alpine:${ALPINE_VERSION} AS stage3
150+
151+
# upgrade system and installed dependencies for security patches
152+
RUN --mount=type=cache,sharing=private,target=/var/cache/apk \
153+
set -eux; \
154+
apk upgrade
155+
156+
# copy prepared structure from stage2
157+
COPY --from=stage2 /usr/local /usr/local
158+
159+
# install dependencies and common packages
160+
RUN --mount=type=cache,sharing=private,target=/var/cache/apk \
161+
set -eux; \
162+
apk add \
163+
curl \
164+
gc-dev \
165+
gc-static \
166+
gcc \
167+
git \
168+
libevent-dev \
169+
libevent-static \
170+
musl-dev \
171+
openssl-dev \
172+
openssl-libs-static \
173+
pcre2-dev \
174+
pcre2-static \
175+
sqlite-dev \
176+
sqlite-static \
177+
tzdata \
178+
yaml-dev \
179+
yaml-static \
180+
zlib-dev \
181+
zlib-static \
182+
; \
183+
# smoke tests
184+
[ "$(command -v crystal)" = '/usr/local/bin/crystal' ]; \
185+
[ "$(command -v shards)" = '/usr/local/bin/shards' ]; \
186+
crystal --version; \
187+
shards --version
188+
189+
# setup non-root user (fixuid)
190+
RUN --mount=type=cache,sharing=private,target=/var/cache/apk \
191+
--mount=type=tmpfs,target=/tmp \
192+
set -eux -o pipefail; \
193+
# create non-root user & give passwordless sudo
194+
{ \
195+
apk add sudo; \
196+
addgroup -g 1000 user; \
197+
adduser -u 1000 -G user -h /home/user -s /bin/sh -D user; \
198+
mkdir -p /etc/sudoers.d; \
199+
echo "user ALL=(root) NOPASSWD:ALL" > /etc/sudoers.d/user; \
200+
# cleanup backup copies
201+
rm /etc/group- /etc/passwd- /etc/shadow-; \
202+
}; \
203+
# Install fixuid
204+
{ \
205+
cd /tmp; \
206+
export FIXUID_VERSION=0.6.0; \
207+
case "$(arch)" in \
208+
x86_64) \
209+
export \
210+
FIXUID_ARCH=amd64 \
211+
FIXUID_SHA256=8c47f64ec4eec60e79871796ea4097ead919f7fcdedace766da9510b78c5fa14 \
212+
; \
213+
;; \
214+
aarch64) \
215+
export \
216+
FIXUID_ARCH=arm64 \
217+
FIXUID_SHA256=827e0b480c38470b5defb84343be7bb4e85b9efcbf3780ac779374e8b040a969 \
218+
; \
219+
;; \
220+
esac; \
221+
wget -q -O fixuid.tar.gz https://github.com/boxboat/fixuid/releases/download/v${FIXUID_VERSION}/fixuid-${FIXUID_VERSION}-linux-${FIXUID_ARCH}.tar.gz; \
222+
echo "${FIXUID_SHA256} *fixuid.tar.gz" | sha256sum -c - >/dev/null 2>&1; \
223+
tar -xf fixuid.tar.gz; \
224+
mv fixuid /usr/local/bin/; \
225+
chmod u+s /usr/local/bin/fixuid; \
226+
rm fixuid.tar.gz; \
227+
}; \
228+
# Generate fixuid config
229+
mkdir -p /etc/fixuid; \
230+
{ \
231+
echo "user: user"; \
232+
echo "group: user"; \
233+
} | tee /etc/fixuid/config.yml
234+
235+
# Adjust Overmind socket location
236+
ENV OVERMIND_SOCKET=/tmp/overmind.sock
237+
238+
# Adjust ENTRYPOINT
239+
ENTRYPOINT [ "/usr/local/bin/fixuid", "-q" ]
240+
CMD [ "/bin/sh" ]
241+
242+
# install development utilities
243+
RUN --mount=type=cache,sharing=private,target=/var/cache/apk \
244+
--mount=type=tmpfs,target=/tmp \
245+
set -eux; \
246+
cd /tmp; \
247+
# Overmind (needs tmux)
248+
{ \
249+
export OVERMIND_VERSION=2.5.1; \
250+
case "$(arch)" in \
251+
x86_64) \
252+
export \
253+
OVERMIND_ARCH=amd64 \
254+
OVERMIND_SHA256=a17159b8e97d13f3679a4e8fbc9d4747f82d5af9f6d32597b72821378b5d0b6f \
255+
; \
256+
;; \
257+
aarch64) \
258+
export \
259+
OVERMIND_ARCH=arm64 \
260+
OVERMIND_SHA256=42cb6d79c8adcf4c68dfb2ddf09e63a0803b023af5b17d42e05ccbfa4b86bee2 \
261+
; \
262+
;; \
263+
esac; \
264+
apk add \
265+
tmux \
266+
; \
267+
curl --fail -Lo overmind.gz https://github.com/DarthSim/overmind/releases/download/v${OVERMIND_VERSION}/overmind-v${OVERMIND_VERSION}-linux-${OVERMIND_ARCH}.gz; \
268+
echo "${OVERMIND_SHA256} *overmind.gz" | sha256sum -c - >/dev/null 2>&1; \
269+
gunzip overmind.gz; \
270+
chmod +x overmind; \
271+
mv overmind /usr/local/bin/; \
272+
}; \
273+
# Watchexec
274+
{ \
275+
export WATCHEXEC_VERSION=2.2.1; \
276+
case "$(arch)" in \
277+
x86_64) \
278+
export \
279+
WATCHEXEC_ARCH=x86_64 \
280+
WATCHEXEC_SHA256=74651d6f450bca5436eee35b7828f1b97388d3b3976da313db36e3a91f7ada44 \
281+
; \
282+
;; \
283+
aarch64) \
284+
export \
285+
WATCHEXEC_ARCH=aarch64 \
286+
WATCHEXEC_SHA256=87ec2094f2e883a090cb4a72a073f9b44f4aba7f50481f068e175f993d15c581 \
287+
; \
288+
;; \
289+
esac; \
290+
curl --fail -Lo watchexec.tar.xz https://github.com/watchexec/watchexec/releases/download/v${WATCHEXEC_VERSION}/watchexec-${WATCHEXEC_VERSION}-${WATCHEXEC_ARCH}-unknown-linux-musl.tar.xz; \
291+
echo "${WATCHEXEC_SHA256} *watchexec.tar.xz" | sha256sum -c - >/dev/null 2>&1; \
292+
tar -xf watchexec.tar.xz; \
293+
mv watchexec-${WATCHEXEC_VERSION}-${WATCHEXEC_ARCH}-unknown-linux-musl/watchexec /usr/local/bin/; \
294+
rm -rf watchexec.tar.xz watchexec-${WATCHEXEC_VERSION}-${WATCHEXEC_ARCH}-unknown-linux-musl; \
295+
}; \
296+
# smoke tests
297+
[ "$(command -v overmind)" = '/usr/local/bin/overmind' ]; \
298+
[ "$(command -v watchexec)" = '/usr/local/bin/watchexec' ]; \
299+
overmind --version; \
300+
watchexec --version

0 commit comments

Comments
 (0)