/crystal-container-images

Multi-arch Crystal images for multiple OSes

Primary LanguageDockerfileMIT LicenseMIT

Crystal container images and DEB/RPM packages

Multi-architecture (amd64 and arm64) container image and DEB/RPM package builder for the Crystal compiler. The images are built daily using GitHub actions.

The container images are published at https://hub.docker.com/r/84codes/crystal and the packages at https://packagecloud.com/84codes/crystal

Usage

Use these images when you want to build your Crystal app, (pro tip: always use a multi stage approach).

FROM 84codes/crystal:1.4.1-ubuntu-22.04 AS builder
WORKDIR /usr/src/app
# Copying and install dependencies
COPY shard.yml shard.lock .
RUN shards install --production
# Copying the rest of the code
COPY src src
# Build binaries
RUN shards build --release --no-debug

# start from a clean ubuntu image
FROM ubuntu:22.04
# install required dependencies
RUN apt-get update && \
    apt-get install -y libssl3 libevent-2.1-7 && \
    apt-get clean && \
    rm -rf /var/cache/apt/* /var/lib/apt/lists/* /var/cache/debconf/* /var/log/*
# copy the compiled binary from the build stage
COPY --from=builder /usr/src/app/bin/* /usr/local/bin/
ENTRYPOINT ["/usr/local/bin/myapp"]

Smallest images are achieved with static compiled binaries added to a scratch image:

# Compile in a build stage
FROM 84codes/crystal:1.4.1-alpine-latest as builder
WORKDIR /tmp
# Copying and install dependencies
COPY shard.yml shard.lock ./
RUN shards install --production
# Copy the rest of the code
COPY src/ src/
# Build a static binary
RUN shards build --release --production --static --no-debug

# The scratch image is completely empty
FROM scratch
# Don't run as root
USER 2:2
# Copy only the binary from the build stage
COPY --from=builder /tmp/bin/* /
# Install a CA store, only needed if the application verifies TLS peers (eg. talk to a https server)
COPY --from=builder /etc/ssl/cert.pem /etc/ssl/
# Set default entrypoint
ENTRYPOINT ["/myapp"]

Supported OSes and versions

  • Alpine latest
  • Ubuntu 20.04
  • Ubuntu 22.04
  • Debian Buster
  • Debian Bullseye
  • Fedora 35
  • Fedora 36

Supported Crystal version(s)

More versions are easily added, but currently images are build for these Crystal versions:

  • 1.4.1

DEB/RPM packages

DEB and RPM packages are built both for amd64 and arm64, and published at https://packagecloud.io/84codes/crystal.

For best performance use dynamically built packages, they link to the distribution's libraries (there for only a few current versions are supported). For other distributions and versions, use the statically compiled binaries.

Install

Dynamically linked binaries for recent and current Ubuntu/Debian versions

curl -fsSL https://packagecloud.io/84codes/crystal/gpgkey | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/84codes_crystal.gpg
. /etc/os-release
echo "deb https://packagecloud.io/84codes/crystal/$ID $VERSION_CODENAME main" | sudo tee /etc/apt/sources.list.d/84codes_crystal.list
apt-get update
apt-get install crystal

Dynamically linked binaries for recent and current Fedora versions

sudo tee /etc/yum.repos.d/84codes_crystal.repo << 'EOF'
[84codes_crystal]
name=84codes_crystal
baseurl=https://packagecloud.io/84codes/crystal/fedora/$releasever/$basearch
gpgkey=https://packagecloud.io/84codes/crystal/gpgkey
repo_gpgcheck=1
gpgcheck=0
EOF
sudo dnf install crystal

Any Deb based distributions

curl -fsSL https://packagecloud.io/84codes/crystal/gpgkey | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/84codes_crystal.gpg
echo "deb https://packagecloud.io/84codes/crystal/any any main" | sudo tee /etc/apt/sources.list.d/84codes_crystal.list
apt-get update
apt-get install crystal

Any RPM based distributions

sudo tee /etc/yum.repos.d/84codes_crystal.repo << 'EOF'
[84codes_crystal]
name=84codes_crystal
baseurl=https://packagecloud.io/84codes/crystal/rpm_any/rpm_any/$basearch
gpgkey=https://packagecloud.io/84codes/crystal/gpgkey
repo_gpgcheck=1
gpgcheck=0
EOF
sudo dnf install crystal

The static packages are built using the binaries from the alpine container and packaged up using fpm.

The alpine image is built (multi-arch using buildx+qemu), then in the pkgs dockerfile the files from the alpine container are packaged up and copied to a scratch image, from which the packages are exported and then uploaded to packagecloud.

For details please see: