From 1851ab69a1ded524cdebc9db545108e40f898e55 Mon Sep 17 00:00:00 2001 From: Caspian Baska Date: Wed, 2 Jun 2021 14:46:57 +1000 Subject: [PATCH 1/5] build!: progress towards static musl builds --- Dockerfile | 132 ++++++++++++++++++++++++------------- Dockerfile.test | 99 +++++++++++++++++++++------- scripts/entrypoint-test.sh | 13 ++-- 3 files changed, 167 insertions(+), 77 deletions(-) diff --git a/Dockerfile b/Dockerfile index 67a5c1f..9d42b7e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,82 +1,122 @@ ARG CRYSTAL_VERSION=1.0.0 -FROM crystallang/crystal:${CRYSTAL_VERSION} as build -ARG PLACE_COMMIT=DEV +# Digest CLI +############################################################################### +FROM crystallang/crystal:${CRYSTAL_VERSION} as digest + +ARG CRYSTAL_VERSION=1.0.0 +ARG PLACE_COMMIT="DEV" WORKDIR /app -RUN apt update -RUN apt install --no-install-recommends -y \ +RUN apt-get update && \ + apt-get install -y apt-transport-https && \ + apt-get update && \ + DEBIAN_FRONTEND=noninteractive \ + apt install --no-install-recommends -y \ bash \ ca-certificates \ curl \ - git \ - libssh2-1 libssh2-1-dev \ - libgc-dev \ llvm-10 llvm-10-dev \ - tzdata + libssh2-1 libssh2-1-dev \ + libyaml-dev \ + && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* -# Add trusted CAs for communicating with external services -RUN update-ca-certificates +# Install shards before adding source. +COPY shard.yml /app +COPY shard.lock /app +RUN shards install --ignore-crystal-version -# Create a non-privileged user -ARG IMAGE_UID="10001" -ENV UID=$IMAGE_UID -ENV USER=appuser -RUN adduser \ - --disabled-password \ - --gecos "" \ - --home "/nonexistent" \ - --shell "/sbin/nologin" \ - --no-create-home \ - --uid "${UID}" \ - "${USER}" +# Build digest tool before copying rest of source for better caching. +COPY src/digest_cli.cr /app/src/digest_cli.cr +RUN CRYSTAL_PATH=lib:/usr/share/crystal/src/ \ + LLVM_CONFIG=$(/usr/share/crystal/src/llvm/ext/find-llvm-config) \ + shards build digest_cli -Dpreview_mt --ignore-crystal-version --no-debug --production -# These provide certificate chain validation where communicating with external services over TLS -ENV SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt +# Extract dependencies +RUN ldd /app/bin/digest_cli | tr -s '[:blank:]' '\n' | grep '^/' | xargs -I % sh -c 'mkdir -p $(dirname deps%); cp % deps%;' -# Create binary directories -RUN mkdir -p repositories bin/drivers +# Build +############################################################################### -RUN mkdir /app/.shards +FROM crystallang/crystal:${CRYSTAL_VERSION}-alpine as build -# Install deps -COPY shard.yml /app -COPY shard.lock /app +ARG CRYSTAL_VERSION=1.0.0 +ARG PLACE_COMMIT="DEV" -RUN shards install --production --ignore-crystal-version +WORKDIR /app -# Copy source for the long building `digest_cli` -RUN mkdir /app/src -COPY src/digest_cli.cr /app/src/digest_cli.cr +# Install the latest version of LibSSH2, ping, etc +RUN apk add --no-cache \ + bash \ + ca-certificates \ + curl \ + iputils \ + libssh2-static \ + yaml-static + +# Add a glibc shim +# NOTE: Once musl builds are a supported target, `asdf` should be updated to use those builds +RUN mkdir keys && (cd keys && curl -slO https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub) && \ + curl -sLO https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.33-r0/glibc-2.33-r0.apk && \ + curl -sLO https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.33-r0/glibc-i18n-2.33-r0.apk && \ + curl -sLO https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.33-r0/glibc-bin-2.33-r0.apk && \ + curl -sLO https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.33-r0/glibc-dev-2.33-r0.apk && \ + apk add --allow-untrusted --keys-dir keys glibc-2.33-r0.apk && \ + apk add --allow-untrusted --keys-dir keys glibc-dev-2.33-r0.apk && \ + apk add --allow-untrusted --keys-dir keys glibc-bin-2.33-r0.apk && \ + apk add --allow-untrusted --keys-dir keys glibc-i18n-2.33-r0.apk && \ + rm -r keys *.apk -RUN CRYSTAL_PATH=lib:/usr/share/crystal/src/ \ - LLVM_CONFIG=$(/usr/share/crystal/src/llvm/ext/find-llvm-config) \ - PLACE_COMMIT=${PLACE_COMMIT} \ - UNAME_AT_COMPILE_TIME=true \ - shards build --error-trace --ignore-crystal-version --release --production -Dpreview_mt digest_cli +# Add trusted CAs for communicating with external services +RUN update-ca-certificates + +# Install shards before adding source. +COPY shard.yml /app +COPY shard.lock /app +RUN shards install --ignore-crystal-version + +# Copy the `digest_cli` binary, and all of its runtime dependencies +COPY --from=digest /app/deps / +COPY --from=digest /app/bin/digest_cli /app/bin # Add the rest of the source last for efficient caching +COPY scripts /app/scripts COPY src /app/src RUN PLACE_COMMIT=${PLACE_COMMIT} \ UNAME_AT_COMPILE_TIME=true \ - shards build --error-trace --ignore-crystal-version --release --production -Dpreview_mt build - -RUN chown appuser -R /app + shards build --error-trace -Dpreview_mt --release --ignore-crystal-version --production build ############################################################################### -USER appuser:appuser +ENV HOME="/app" +ENV CRYSTAL_VERSION=$CRYSTAL_VERSION +ENV SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt + +# Create a non-privileged user +ARG IMAGE_UID="10001" +ENV UID=$IMAGE_UID +ENV USER=appuser +RUN adduser \ + --disabled-password \ + --gecos "" \ + --home "${HOME}" \ + --shell "/sbin/nologin" \ + --uid "${UID}" \ + "${USER}" # Install asdf version manager SHELL ["/bin/bash", "-l", "-c"] -RUN git clone https://github.com/asdf-vm/asdf.git $HOME/.asdf --branch v0.8.0 -RUN $HOME/.asdf/bin/asdf plugin-add crystal https://github.com/asdf-community/asdf-crystal.git -RUN echo -e '\n. $HOME/.asdf/asdf.sh' >> ~/.bashrc && \ +RUN git clone --depth 1 https://github.com/asdf-vm/asdf.git $HOME/.asdf --branch v0.8.0 && \ + $HOME/.asdf/bin/asdf plugin-add crystal https://github.com/asdf-community/asdf-crystal.git && \ + echo -e '\n. $HOME/.asdf/asdf.sh' >> ~/.bashrc && \ echo -e '\n. $HOME/.asdf/asdf.sh' >> ~/.profile && \ source ~/.bashrc +RUN chown appuser -R "${HOME}" +USER appuser:appuser + EXPOSE 3000 HEALTHCHECK CMD wget -qO- http://localhost:3000/api/build/v1 CMD ["/app/scripts/entrypoint.sh", "--server", "-b", "0.0.0.0", "-p", "3000"] diff --git a/Dockerfile.test b/Dockerfile.test index 0d175a8..66802ef 100644 --- a/Dockerfile.test +++ b/Dockerfile.test @@ -1,25 +1,26 @@ ARG CRYSTAL_VERSION=1.0.0 -FROM crystallang/crystal:${CRYSTAL_VERSION} +# Digest CLI +############################################################################### +FROM crystallang/crystal:${CRYSTAL_VERSION} as digest + +ARG CRYSTAL_VERSION=1.0.0 ARG PLACE_COMMIT="DEV" WORKDIR /app -RUN apt update -RUN apt install --no-install-recommends -y \ +RUN apt-get update && \ + apt-get install -y apt-transport-https && \ + apt-get update && \ + DEBIAN_FRONTEND=noninteractive \ + apt install --no-install-recommends -y \ bash \ ca-certificates \ curl \ - libssh2-1 libssh2-1-dev \ llvm-10 llvm-10-dev \ - -# Install watchexec -RUN curl -sLO https://github.com/watchexec/watchexec/releases/download/cli-v1.16.0/watchexec-1.16.0-x86_64-unknown-linux-gnu.deb && \ - dpkg -i watchexec-1.16.0-x86_64-unknown-linux-gnu.deb && \ - rm -rf ./*.deb - -# Add trusted CAs for communicating with external services -RUN update-ca-certificates + libssh2-1 libssh2-1-dev \ + libyaml-dev \ + && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* # Install shards before adding source. COPY shard.yml /app @@ -27,29 +28,81 @@ COPY shard.lock /app RUN shards install --ignore-crystal-version # Build digest tool before copying rest of source for better caching. -RUN mkdir /app/src COPY src/digest_cli.cr /app/src/digest_cli.cr - RUN CRYSTAL_PATH=lib:/usr/share/crystal/src/ \ LLVM_CONFIG=$(/usr/share/crystal/src/llvm/ext/find-llvm-config) \ - shards build digest_cli --ignore-crystal-version --no-debug + shards build digest_cli -Dpreview_mt --ignore-crystal-version --no-debug --production -COPY src/digest_cli.cr /app/src/digest_cli.cr +# Extract dependencies +RUN ldd /app/bin/digest_cli | tr -s '[:blank:]' '\n' | grep '^/' | xargs -I % sh -c 'mkdir -p $(dirname deps%); cp % deps%;' -COPY scripts /app/scripts -COPY src /app/sr +# Build +############################################################################### + +FROM crystallang/crystal:${CRYSTAL_VERSION}-alpine as build + +ARG CRYSTAL_VERSION=1.0.0 +ARG PLACE_COMMIT="DEV" + +WORKDIR /app + +# Install the latest version of LibSSH2, ping, etc +RUN apk add --no-cache \ + bash \ + ca-certificates \ + curl \ + iputils \ + libssh2-static \ + yaml-static -RUN mkdir -p /app/bin/drivers +# Add a glibc shim +# NOTE: Once musl builds are a supported target, `asdf` should be updated to use those builds +RUN mkdir keys && (cd keys && curl -slO https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub) && \ + curl -sLO https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.33-r0/glibc-2.33-r0.apk && \ + curl -sLO https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.33-r0/glibc-i18n-2.33-r0.apk && \ + curl -sLO https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.33-r0/glibc-bin-2.33-r0.apk && \ + curl -sLO https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.33-r0/glibc-dev-2.33-r0.apk && \ + apk add --allow-untrusted --keys-dir keys glibc-2.33-r0.apk && \ + apk add --allow-untrusted --keys-dir keys glibc-dev-2.33-r0.apk && \ + apk add --allow-untrusted --keys-dir keys glibc-bin-2.33-r0.apk && \ + apk add --allow-untrusted --keys-dir keys glibc-i18n-2.33-r0.apk && \ + rm -r keys *.apk + +# Add trusted CAs for communicating with external services +RUN update-ca-certificates + +# Add watchexec +RUN apk add --no-cache -X http://dl-cdn.alpinelinux.org/alpine/edge/testing watchexec + +# Install shards before adding source. +COPY shard.yml /app +COPY shard.lock /app +RUN shards install --ignore-crystal-version + +# Copy the `digest_cli` binary, and all of its runtime dependencies +COPY --from=digest /app/deps / +COPY --from=digest /app/bin/digest_cli /app/bin + +COPY scripts /app/scripts +COPY src /app/src # These provide certificate chain validation where communicating with external services over TLS ENV SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt -# Install asdf version manager +###############################################3############################### + +ENV CRYSTAL_PATH=lib:/usr/share/crystal/src +ENV CRYSTAL_LIBRARY_PATH=/usr/local/lib +ENV CRYSTAL_VERSION=${CRYSTAL_VERSION} + +ENV HOME="/app" SHELL ["/bin/bash", "-l", "-c"] -RUN git clone https://github.com/asdf-vm/asdf.git $HOME/.asdf --branch v0.8.0 && \ + +# Install asdf version manager +RUN git clone --depth 1 https://github.com/asdf-vm/asdf.git $HOME/.asdf --branch v0.8.0 && \ $HOME/.asdf/bin/asdf plugin-add crystal https://github.com/asdf-community/asdf-crystal.git && \ - echo -e '\n. $HOME/.asdf/asdf.sh' >> ~/.bashrc && \ - echo -e '\n. $HOME/.asdf/asdf.sh' >> ~/.profile && \ + echo -e '\n. $HOME/.asdf/asdf.sh' >> $HOME/.bashrc && \ + echo -e '\n. $HOME/.asdf/asdf.sh' >> $HOME/.profile && \ source ~/.bashrc CMD /app/scripts/entrypoint-test.sh diff --git a/scripts/entrypoint-test.sh b/scripts/entrypoint-test.sh index 49454ac..e02c93e 100755 --- a/scripts/entrypoint-test.sh +++ b/scripts/entrypoint-test.sh @@ -2,10 +2,10 @@ set -eu -source $HOME/.asdf/asdf.sh +source ${HOME}/.asdf/asdf.sh -asdf install crystal 1.0.0 -asdf global crystal 1.0.0 +asdf install crystal ${CRYSTAL_VERSION} +asdf global crystal ${CRYSTAL_VERSION} if [ -z ${GITHUB_ACTION+x} ] then @@ -16,9 +16,6 @@ then crystal lib/ameba/bin/ameba.cr fi -export CRYSTAL_PATH=lib:/usr/share/crystal/src -export CRYSTAL_LIBRARY_PATH=/usr/local/lib - watch="false" multithreaded="false" while [[ $# -gt 0 ]] @@ -36,13 +33,13 @@ do esac done -if [[ "$multithreaded" == "true" ]]; then +if [[ "${multithreaded}" == "true" ]]; then args="-Dpreview_mt" else args="" fi -if [[ "$watch" == "true" ]]; then +if [[ "${watch}" == "true" ]]; then CRYSTAL_WORKERS=$(nproc) watchexec -e cr -c -r -w src -w spec -- scripts/crystal-spec.sh -v ${args} else CRYSTAL_WORKERS=$(nproc) scripts/crystal-spec.sh -v ${args} From 35d86fcab0f2be59c2124d94edcc1d7e92835b71 Mon Sep 17 00:00:00 2001 From: Caspian Baska Date: Mon, 5 Jul 2021 18:11:27 +1000 Subject: [PATCH 2/5] build(dockerfile): convert to alpine --- Dockerfile | 98 ++++++++++++++++++++++--------------------------- Dockerfile.test | 62 +++++++++++++------------------ 2 files changed, 69 insertions(+), 91 deletions(-) diff --git a/Dockerfile b/Dockerfile index 47d8822..53288cf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,59 +1,30 @@ ARG CRYSTAL_VERSION=1.0.0 -ARG PLACE_COMMIT="DEV" +FROM crystallang/crystal:${CRYSTAL_VERSION}-alpine-build as build -FROM crystallang/crystal:${CRYSTAL_VERSION} as build +ARG PLACE_COMMIT=DEV +ARG PLACE_VERSION=DEV WORKDIR /app -RUN apt-get update && \ - apt-get install -y apt-transport-https && \ - apt-get update && \ - DEBIAN_FRONTEND=noninteractive \ - apt install --no-install-recommends -y \ - bash \ - ca-certificates \ - curl \ - llvm-10 llvm-10-dev \ - libssh2-1 libssh2-1-dev \ - libyaml-dev \ - && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* +# Install the latest version of LLVM, LibSSH2, ping, curl, git, ca-certificates +RUN apk add --update --no-cache \ + bash \ + ca-certificates \ + curl \ + git \ + iputils \ + libssh2-static \ + llvm llvm-dev \ + yaml-static # Add trusted CAs for communicating with external services RUN update-ca-certificates -# Create binary directories -RUN mkdir -p repositories bin/drivers -# Install watchexec -RUN curl -sLO https://github.com/watchexec/watchexec/releases/download/cli-v1.16.0/watchexec-1.16.0-x86_64-unknown-linux-gnu.deb && \ - dpkg -i watchexec-1.16.0-x86_64-unknown-linux-gnu.deb && \ - rm -rf ./*.deb - -RUN mkdir -p /app/bin/drivers - -# Install shards before adding source. -COPY shard.yml /app -COPY shard.lock /app -RUN shards install --ignore-crystal-version - -# Build digest tool before copying rest of source for better caching. -COPY src/digest_cli.cr /app/src/digest_cli.cr -RUN CRYSTAL_PATH=lib:/usr/share/crystal/src/ \ - LLVM_CONFIG=$(/usr/share/crystal/src/llvm/ext/find-llvm-config) \ - shards build digest_cli -Dpreview_mt --ignore-crystal-version --no-debug --production - -# Add the rest of the source last for efficient caching -COPY scripts /app/scripts -COPY src /app/src - -RUN PLACE_COMMIT=${PLACE_COMMIT} \ - UNAME_AT_COMPILE_TIME=true \ - shards build --error-trace -Dpreview_mt --release --ignore-crystal-version --production build - -############################################################################### - -ENV HOME="/app" -ENV SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt -ENV CRYSTAL_VERSION=$CRYSTAL_VERSION +# TODO: Awaiting asdf static crystal patch +# +# Install asdf version manager +# RUN git clone https://github.com/asdf-vm/asdf.git /app/.asdf --branch v0.8.0 +# RUN /app/.asdf/bin/asdf plugin-add crystal https://github.com/asdf-community/asdf-crystal.git # Create a non-privileged user ARG IMAGE_UID="10001" @@ -68,18 +39,35 @@ RUN adduser \ --uid "${UID}" \ "${USER}" +# These provide certificate chain validation where communicating with external services over TLS +ENV SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt + +# Create binary directories +RUN mkdir -p repositories bin/drivers + +RUN mkdir /app/.shards + +# Install deps +COPY shard.yml /app +COPY shard.lock /app + +RUN shards install --production --ignore-crystal-version + +# Add source last for efficient caching +COPY src /app/src + +# Build the required target +RUN CRYSTAL_PATH=lib:/usr/share/crystal/src/ \ + LLVM_CONFGI=$(/usr/share/crystal/src/llvm/ext/find-llvm-config) \ + PLACE_COMMIT=${PLACE_COMMIT} \ + UNAME_AT_COMPILE_TIME=true \ + shards build --error-trace --ignore-crystal-version --production + RUN chown appuser -R /app -# Install asdf version manager -SHELL ["/bin/bash", "-l", "-c"] -RUN git clone --depth 1 https://github.com/asdf-vm/asdf.git $HOME/.asdf --branch v0.8.0 && \ - $HOME/.asdf/bin/asdf plugin-add crystal https://github.com/asdf-community/asdf-crystal.git && \ - echo -e '\n. $HOME/.asdf/asdf.sh' >> ~/.bashrc && \ - echo -e '\n. $HOME/.asdf/asdf.sh' >> ~/.profile && \ - source ~/.bashrc +############################################################################### USER appuser:appuser -RUN chown appuser -R /app EXPOSE 3000 HEALTHCHECK CMD wget -qO- http://localhost:3000/api/build/v1 diff --git a/Dockerfile.test b/Dockerfile.test index 51f81f7..573ae73 100644 --- a/Dockerfile.test +++ b/Dockerfile.test @@ -1,58 +1,48 @@ ARG CRYSTAL_VERSION=1.0.0 -ARG PLACE_COMMIT="DEV" +FROM crystallang/crystal:${CRYSTAL_VERSION}-alpine-build -FROM crystallang/crystal:${CRYSTAL_VERSION} as build +ARG PLACE_COMMIT="DEV" WORKDIR /app -RUN apt-get update && \ - apt-get install -y apt-transport-https && \ - apt-get update && \ - DEBIAN_FRONTEND=noninteractive \ - apt install --no-install-recommends -y \ +# Install the latest version of LibSSH2, ping, curl, git +RUN apk add --update --no-cache \ bash \ ca-certificates \ curl \ - llvm-10 llvm-10-dev \ - libssh2-1 libssh2-1-dev \ - libyaml-dev \ - && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* - -# Add trusted CAs for communicating with external services -RUN update-ca-certificates + git \ + iputils \ + libssh2-static \ + llvm llvm-dev \ + yaml-static -# Install watchexec -RUN curl -sLO https://github.com/watchexec/watchexec/releases/download/cli-v1.16.0/watchexec-1.16.0-x86_64-unknown-linux-gnu.deb && \ - dpkg -i watchexec-1.16.0-x86_64-unknown-linux-gnu.deb && \ - rm -rf ./*.deb +RUN apk add --update --no-cache -X http://dl-cdn.alpinelinux.org/alpine/edge/testing watchexec # Add trusted CAs for communicating with external services RUN update-ca-certificates -# Install shards before adding source. +# Awaiting asdf patch for static compiler builds +# +# SHELL ["/bin/bash", "-l", "-c"] +# +# # Install asdf version manager +# RUN git clone https://github.com/asdf-vm/asdf.git $HOME/.asdf --branch v0.8.0 +# RUN $HOME/.asdf/bin/asdf plugin-add crystal https://github.com/asdf-community/asdf-crystal.git +# +# RUN echo -e '\n. $HOME/.asdf/asdf.sh' >> ~/.bashrc && \ +# echo -e '\n. $HOME/.asdf/asdf.sh' >> ~/.profile && \ +# source ~/.bashrc + COPY shard.yml /app COPY shard.lock /app + RUN shards install --ignore-crystal-version -# Build digest tool before copying rest of source for better caching. -COPY src/digest_cli.cr /app/src/digest_cli.cr -RUN CRYSTAL_PATH=lib:/usr/share/crystal/src/ \ - LLVM_CONFIG=$(/usr/share/crystal/src/llvm/ext/find-llvm-config) \ - shards build digest_cli -Dpreview_mt --ignore-crystal-version --no-debug --production +COPY scripts/* /app/scripts/ -COPY scripts /app/scripts -COPY src /app/src +RUN mkdir -p /app/bin/drivers -ENV HOME="/app" +# These provide certificate chain validation where communicating with external services over TLS ENV SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt -SHELL ["/bin/bash", "-l", "-c"] -# Install asdf version manager -RUN git clone --depth 1 https://github.com/asdf-vm/asdf.git $HOME/.asdf --branch v0.8.0 && \ - $HOME/.asdf/bin/asdf plugin-add crystal https://github.com/asdf-community/asdf-crystal.git && \ - echo -e '\n. $HOME/.asdf/asdf.sh' >> $HOME/.bashrc && \ - echo -e '\n. $HOME/.asdf/asdf.sh' >> $HOME/.profile && \ - source ~/.bashrc - - CMD /app/scripts/entrypoint-test.sh From e0b50afe03fc2ae6e4fdace25dfe92a67e30b41a Mon Sep 17 00:00:00 2001 From: Caspian Baska Date: Tue, 6 Jul 2021 14:11:40 +1000 Subject: [PATCH 3/5] build(Dockerfile): convert to alpine --- .gitignore | 11 +++++----- Dockerfile | 45 ++++++++++++++++++++++++++++---------- Dockerfile.test | 19 +++++++++++++--- scripts/build_llvm_ext.sh | 6 +++++ scripts/entrypoint-test.sh | 9 ++++---- scripts/entrypoint.sh | 3 ++- 6 files changed, 67 insertions(+), 26 deletions(-) create mode 100755 scripts/build_llvm_ext.sh diff --git a/.gitignore b/.gitignore index 0cbb10c..6fb693e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,9 @@ -docs/ -lib/ -bin/ -.shards/ *.dwarf .DS_* +.shards/ .tool-versions -repositories -binaries +bin/ build_app +docs/ +lib/ +repositories/ diff --git a/Dockerfile b/Dockerfile index 53288cf..a07bb6f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,27 +1,47 @@ ARG CRYSTAL_VERSION=1.0.0 -FROM crystallang/crystal:${CRYSTAL_VERSION}-alpine-build as build +FROM crystallang/crystal:${CRYSTAL_VERSION}-alpine-build as build-digest + +WORKDIR /app + +# Install the latest version of LLVM, LibSSH2, ping, git, ca-certificates +RUN apk add --update --no-cache \ + bash \ + yaml-static + +# Build a missing llvm artefact. +COPY scripts/build_llvm_ext.sh build_llvm_ext.sh +RUN ./build_llvm_ext.sh + +COPY shard.* . +RUN shards install --production --ignore-crystal-version + +COPY src/digest_cli.cr src/digest_cli.cr + +# Build the required target +RUN CRYSTAL_PATH=lib:/usr/share/crystal/src/ \ + LLVM_CONFIG=$(/usr/share/crystal/src/llvm/ext/find-llvm-config) \ + shards build --error-trace --ignore-crystal-version --production digest_cli && \ + rm /usr/share/crystal/src/llvm/ext/llvm_ext.o + +FROM crystallang/crystal:${CRYSTAL_VERSION}-alpine as build ARG PLACE_COMMIT=DEV ARG PLACE_VERSION=DEV WORKDIR /app -# Install the latest version of LLVM, LibSSH2, ping, curl, git, ca-certificates +# Install the latest version of LLVM, LibSSH2, ping, git, ca-certificates RUN apk add --update --no-cache \ bash \ ca-certificates \ - curl \ - git \ iputils \ libssh2-static \ - llvm llvm-dev \ yaml-static # Add trusted CAs for communicating with external services RUN update-ca-certificates # TODO: Awaiting asdf static crystal patch -# # Install asdf version manager # RUN git clone https://github.com/asdf-vm/asdf.git /app/.asdf --branch v0.8.0 # RUN /app/.asdf/bin/asdf plugin-add crystal https://github.com/asdf-community/asdf-crystal.git @@ -57,11 +77,12 @@ RUN shards install --production --ignore-crystal-version COPY src /app/src # Build the required target -RUN CRYSTAL_PATH=lib:/usr/share/crystal/src/ \ - LLVM_CONFGI=$(/usr/share/crystal/src/llvm/ext/find-llvm-config) \ - PLACE_COMMIT=${PLACE_COMMIT} \ +RUN PLACE_COMMIT=${PLACE_COMMIT} \ + PLACE_VERSION=${PLACE_VERSION} \ UNAME_AT_COMPILE_TIME=true \ - shards build --error-trace --ignore-crystal-version --production + shards build --error-trace --ignore-crystal-version --production build + +COPY --from=build-digest /app/bin/digest_cli /app/bin RUN chown appuser -R /app @@ -70,5 +91,5 @@ RUN chown appuser -R /app USER appuser:appuser EXPOSE 3000 -HEALTHCHECK CMD wget -qO- http://localhost:3000/api/build/v1 -CMD ["/app/scripts/entrypoint.sh", "--server", "-b", "0.0.0.0", "-p", "3000"] +HEALTHCHECK CMD /app/bin/build server --curl http://localhost:3000/api/build/v1 +CMD ["/app/scripts/entrypoint.sh", server, "-b", "0.0.0.0", "-p", "3000"] diff --git a/Dockerfile.test b/Dockerfile.test index 573ae73..ff0c530 100644 --- a/Dockerfile.test +++ b/Dockerfile.test @@ -13,7 +13,7 @@ RUN apk add --update --no-cache \ git \ iputils \ libssh2-static \ - llvm llvm-dev \ + # llvm llvm-dev \ yaml-static RUN apk add --update --no-cache -X http://dl-cdn.alpinelinux.org/alpine/edge/testing watchexec @@ -33,14 +33,27 @@ RUN update-ca-certificates # echo -e '\n. $HOME/.asdf/asdf.sh' >> ~/.profile && \ # source ~/.bashrc +RUN mkdir -p /app/bin/drivers + +# Build a missing llvm artefact. +COPY scripts/build_llvm_ext.sh build_llvm_ext.sh +RUN ./build_llvm_ext.sh + COPY shard.yml /app COPY shard.lock /app RUN shards install --ignore-crystal-version -COPY scripts/* /app/scripts/ +COPY src/digest_cli.cr src/digest_cli.cr -RUN mkdir -p /app/bin/drivers +RUN CRYSTAL_PATH=lib:/usr/share/crystal/src/ \ + LLVM_CONFIG=$(/usr/share/crystal/src/llvm/ext/find-llvm-config) \ + PLACE_COMMIT=${PLACE_COMMIT} \ + UNAME_AT_COMPILE_TIME=true \ + shards build --error-trace --ignore-crystal-version digest_cli && \ + rm /usr/share/crystal/src/llvm/ext/llvm_ext.o + +COPY scripts/* /app/scripts/ # These provide certificate chain validation where communicating with external services over TLS ENV SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt diff --git a/scripts/build_llvm_ext.sh b/scripts/build_llvm_ext.sh new file mode 100755 index 0000000..e447ae3 --- /dev/null +++ b/scripts/build_llvm_ext.sh @@ -0,0 +1,6 @@ +#! /usr/bin/env bash + +CRYSTAL_PATH=/usr/share/crystal/src +LLVM_CONFIG=$(/usr/share/crystal/src/llvm/ext/find-llvm-config) + +cc -c -g -O3 "$CRYSTAL_PATH/llvm/ext/llvm_ext.cc" -o "$CRYSTAL_PATH/llvm/ext/llvm_ext.o" $($LLVM_CONFIG --cxxflags) diff --git a/scripts/entrypoint-test.sh b/scripts/entrypoint-test.sh index bb4e833..5820dd5 100755 --- a/scripts/entrypoint-test.sh +++ b/scripts/entrypoint-test.sh @@ -2,10 +2,11 @@ set -eu -source $HOME/.asdf/asdf.sh - -asdf install crystal 1.0.0 -asdf global crystal 1.0.0 +# TODO: add once asdf patched for glibc crystal +# source $HOME/.asdf/asdf.sh +# +# asdf install crystal 1.0.0 +# asdf global crystal 1.0.0 if [ -z ${GITHUB_ACTION+x} ] then diff --git a/scripts/entrypoint.sh b/scripts/entrypoint.sh index f0c72de..d68a29e 100755 --- a/scripts/entrypoint.sh +++ b/scripts/entrypoint.sh @@ -2,6 +2,7 @@ set -eu -source $HOME/.asdf/asdf.sh +# TODO: After asdf support added +# source $HOME/.asdf/asdf.sh /app/bin/build "$@" From ec08cc6c7c74c0405c8e8ebd0adee8b8cd5cb501 Mon Sep 17 00:00:00 2001 From: Caspian Baska Date: Tue, 6 Jul 2021 14:29:21 +1000 Subject: [PATCH 4/5] feat(api/root): implement healthcheck and version --- shard.lock | 48 +++++++++++++++++++++++++++++++++++ shard.yml | 3 +++ src/placeos-build/api/root.cr | 37 +++++++++++++++++++++++++++ 3 files changed, 88 insertions(+) create mode 100644 src/placeos-build/api/root.cr diff --git a/shard.lock b/shard.lock index bdf1abd..ad6dbc5 100644 --- a/shard.lock +++ b/shard.lock @@ -1,9 +1,17 @@ version: 2.0 shards: + CrystalEmail: + git: https://github.com/nephos/crystalemail.git + version: 0.2.4 + action-controller: git: https://github.com/spider-gazelle/action-controller.git version: 4.5.0 + active-model: + git: https://github.com/spider-gazelle/active-model.git + version: 3.1.1 + ameba: git: https://github.com/crystal-ameba/ameba.git version: 0.14.3 @@ -16,6 +24,10 @@ shards: git: https://github.com/taylorfinnell/awscr-signer.git version: 0.8.2 + bindata: + git: https://github.com/spider-gazelle/bindata.git + version: 1.9.0 + clip: git: https://github.com/erdnaxeli/clip.git version: 0.2.4 @@ -32,6 +44,10 @@ shards: git: https://github.com/kostya/cron_parser.git version: 0.4.0 + db: + git: https://github.com/crystal-lang/crystal-db.git + version: 0.10.1 + debug: git: https://github.com/sija/debug.cr.git version: 2.0.1 @@ -68,6 +84,14 @@ shards: git: https://github.com/sija/ipaddress.cr.git version: 0.2.1 + json_mapping: + git: https://github.com/crystal-lang/json_mapping.cr.git + version: 0.1.1 + + jwt: + git: https://github.com/crystal-community/jwt.git + version: 1.5.1 + log_helper: git: https://github.com/spider-gazelle/log_helper.git version: 1.0.3 @@ -84,6 +108,10 @@ shards: git: https://github.com/aca-labs/murmur3.git version: 0.1.1+git.commit.7cbe25c0ca8d052c9d98c377c824dcb0e038c790 + neuroplastic: + git: https://github.com/spider-gazelle/neuroplastic.git + version: 1.7.1 + open_api: git: https://github.com/elbywan/open_api.cr.git version: 1.3.0 @@ -92,6 +120,10 @@ shards: git: https://github.com/place-labs/openapi-generator.git version: 2.1.0+git.commit.d925772ae1f36c51c0665d743bba4ac6ca9466a8 + openssl_ext: + git: https://github.com/spider-gazelle/openssl_ext.git + version: 2.1.5 + placeos-compiler: git: https://github.com/placeos/compiler.git version: 4.3.1 @@ -104,6 +136,10 @@ shards: git: https://github.com/place-labs/log-backend.git version: 0.4.0 + placeos-models: + git: https://github.com/placeos/models.git + version: 5.7.0 + pool: git: https://github.com/ysbaddaden/pool.git version: 0.2.4 @@ -124,6 +160,14 @@ shards: git: https://github.com/caspiano/rendezvous-hash.git version: 0.3.1 + rethinkdb: + git: https://github.com/kingsleyh/crystal-rethinkdb.git + version: 0.2.3 + + rethinkdb-orm: + git: https://github.com/spider-gazelle/rethinkdb-orm.git + version: 4.1.0 + retriable: git: https://github.com/sija/retriable.cr.git version: 0.2.4 @@ -164,3 +208,7 @@ shards: git: https://github.com/manastech/webmock.cr.git version: 0.14.0 + yaml_mapping: + git: https://github.com/crystal-lang/yaml_mapping.cr.git + version: 0.1.1 + diff --git a/shard.yml b/shard.yml index 5ee58f9..758f3dc 100644 --- a/shard.yml +++ b/shard.yml @@ -40,6 +40,9 @@ dependencies: version: ~> 4 placeos-log-backend: github: place-labs/log-backend + placeos-models: + github: placeos/models + version: ~> 5.6 secrets-env: github: place-labs/secrets-env shards: diff --git a/src/placeos-build/api/root.cr b/src/placeos-build/api/root.cr new file mode 100644 index 0000000..0d5a532 --- /dev/null +++ b/src/placeos-build/api/root.cr @@ -0,0 +1,37 @@ +require "../api" +require "./application" + +require "placeos-models/version" + +module PlaceOS::Build::Api + # Routes trigger builds and query the resulting artefacts. + class Root < Application + include ::OpenAPI::Generator::Controller + include ::OpenAPI::Generator::Helpers::ActionController + + base "/api/build/v1" + + get("/", :root, annotations: @[OpenAPI(<<-YAML + summary: Service healthcheck + YAML + )]) do + head code: :ok + end + + get("/version", :version, annotations: @[OpenAPI(<<-YAML + summary: Service version + YAML + )]) do + render status_code: :ok, json: Root.version + end + + class_getter version : PlaceOS::Model::Version do + PlaceOS::Model::Version.new( + service: APP_NAME, + commit: BUILD_COMMIT, + version: VERSION, + build_time: BUILD_TIME, + ) + end + end +end From 16e1f7f34875de6ca90659b46b811775d7a486d9 Mon Sep 17 00:00:00 2001 From: Caspian Baska Date: Tue, 6 Jul 2021 14:46:02 +1000 Subject: [PATCH 5/5] build: release builds, add CRYSTAL_VERSION --- Dockerfile | 6 ++++-- Dockerfile.test | 2 ++ src/constants.cr | 2 ++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index a07bb6f..508e93d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,7 +20,7 @@ COPY src/digest_cli.cr src/digest_cli.cr # Build the required target RUN CRYSTAL_PATH=lib:/usr/share/crystal/src/ \ LLVM_CONFIG=$(/usr/share/crystal/src/llvm/ext/find-llvm-config) \ - shards build --error-trace --ignore-crystal-version --production digest_cli && \ + shards build --release --no-debug --error-trace --ignore-crystal-version --production digest_cli && \ rm /usr/share/crystal/src/llvm/ext/llvm_ext.o FROM crystallang/crystal:${CRYSTAL_VERSION}-alpine as build @@ -76,11 +76,13 @@ RUN shards install --production --ignore-crystal-version # Add source last for efficient caching COPY src /app/src +ENV CRYSTAL_VERSION=$CRYSTAL_VERSION + # Build the required target RUN PLACE_COMMIT=${PLACE_COMMIT} \ PLACE_VERSION=${PLACE_VERSION} \ UNAME_AT_COMPILE_TIME=true \ - shards build --error-trace --ignore-crystal-version --production build + shards build --no-debug --release --error-trace --ignore-crystal-version --production build COPY --from=build-digest /app/bin/digest_cli /app/bin diff --git a/Dockerfile.test b/Dockerfile.test index ff0c530..0e5c197 100644 --- a/Dockerfile.test +++ b/Dockerfile.test @@ -46,6 +46,8 @@ RUN shards install --ignore-crystal-version COPY src/digest_cli.cr src/digest_cli.cr +ENV CRYSTAL_VERSION=$CRYSTAL_VERSION + RUN CRYSTAL_PATH=lib:/usr/share/crystal/src/ \ LLVM_CONFIG=$(/usr/share/crystal/src/llvm/ext/find-llvm-config) \ PLACE_COMMIT=${PLACE_COMMIT} \ diff --git a/src/constants.cr b/src/constants.cr index 62cb21d..ba2ca5a 100644 --- a/src/constants.cr +++ b/src/constants.cr @@ -7,6 +7,8 @@ module PlaceOS::Build BUILD_TIME = {{ system("date -u").chomp.stringify }} BUILD_COMMIT = {{ env("PLACE_COMMIT") || "DEV" }} + CRYSTAL_VERSION = {{ env("CRYSTAL_VERSION") || "latest" }} + # S3 caching #############################################################################