Skip to content

Instantly share code, notes, and snippets.

@paoliniluis
Last active February 10, 2023 15:27
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save paoliniluis/78fe800f06fc7027a20665a429239c1e to your computer and use it in GitHub Desktop.
Save paoliniluis/78fe800f06fc7027a20665a429239c1e to your computer and use it in GitHub Desktop.
###################
# STAGE 1: builder
###################
FROM --platform=linux/amd64 eclipse-temurin:11.0.12_7-jdk-focal as builder
ARG MB_EDITION=oss CI=true
WORKDIR /app/
RUN curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - \
# install Node LTS and Yarn from their repos
&& curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \
&& echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list \
&& apt-get update && apt-get upgrade -y && apt-get install -y git nodejs yarn \
# installing Clojure CLI
&& curl -O https://download.clojure.org/install/linux-install-1.10.3.986.sh && chmod +x linux-install-1.10.3.986.sh && ./linux-install-1.10.3.986.sh \
# downloading certs from AWS and Azure so we don't need to do it in the next step and only install those
&& mkdir /app/certs \
&& curl https://s3.amazonaws.com/rds-downloads/rds-combined-ca-bundle.pem -o /app/certs/rds-combined-ca-bundle.pem \
&& curl https://cacerts.digicert.com/DigiCertGlobalRootG2.crt.pem -o /app/certs/DigiCertGlobalRootG2.crt.pem
COPY . .
RUN INTERACTIVE=false CI=$CI MB_EDITION=$MB_EDITION bin/build
# ###################
# # STAGE 2: runner
# ###################
FROM eclipse-temurin:11.0.12_7-jre-focal as runner
ENV FC_LANG en-US LC_CTYPE en_US.UTF-8
WORKDIR /app/
COPY --from=builder /app/certs/. /app/certs/
# dependencies
# updating everything that doesn't come updated from previous layers
RUN apt-get update && apt-get upgrade -y && apt-get install -y --no-install-recommends ttf-dejavu && \
# importing certs
mkdir -p /etc/ssl/certs/java/cacerts && \
/opt/java/openjdk/bin/keytool -noprompt -import -trustcacerts -alias aws-rds -file /app/certs/rds-combined-ca-bundle.pem -keystore /etc/ssl/certs/java/cacerts/java-keystore -keypass changeit -storepass changeit && \
/opt/java/openjdk/bin/keytool -noprompt -import -trustcacerts -alias azure-cert -file /app/certs/DigiCertGlobalRootG2.crt.pem -keystore /etc/ssl/certs/java/cacerts/java-keystore -keypass changeit -storepass changeit && \
# cleaning everything to reduce container size
apt-get autoremove -y && apt-get autoclean && \
rm -rf /var/lib/apt/lists/* && \
# providing permissions to the nobody user
chown -R nobody:nogroup /app
USER nobody
COPY --from=builder --chown=nobody /app/target/uberjar/metabase.jar /app/
COPY --chown=nobody bin/docker/run_metabase.sh /app/
# expose our default runtime port
EXPOSE 3000
# run it
ENTRYPOINT ["/app/run_metabase.sh"]
@paoliniluis
Copy link
Author

paoliniluis commented Oct 3, 2021

With this previous Dockerfile it's only about doing:

sudo apt-get install qemu-user qemu-user-static binfmt-support
docker buildx create --use
docker buildx build . --platform linux/arm64/v8,linux/amd64 -t repo/metabase:tag --output=type=image,push=true

Docker will first build on amd64 architecture an uberjar that will then end up in 2 runners: one for ARM and one for x86 (watch out as buildx does not support local images) If you want to have final runners locally you have to do the old n' good:
(for ARM)

DOCKER_BUILDKIT=1 docker build . --build_arg MB_EDITION=oss CI=true -t metabase-arch:tag --platform linux/arm64/v8

for x86 (if you run on x86 you can just omit the platform flag)

DOCKER_BUILDKIT=1 docker build . --build_arg MB_EDITION=oss CI=true -t metabase-arch:tag --platform linux/amd64

@paoliniluis
Copy link
Author

difference of sizes (I have a dirty local repo, but this should be comparable) between current alpine and current focal-JRE
image

@paoliniluis
Copy link
Author

Another thing to add: if someone wants to bundle Metabase into the runner (not build it from scratch, which is not recommended, we recommend using release files), just:

  1. delete the first stage of the Dockerfile
  2. download the metabase JAR you need by doing
curl https://downloads.metabase.com/latest/metabase.jar -o metabase.jar
  1. run the following in the directory where the Dockerfile is
curl https://s3.amazonaws.com/rds-downloads/rds-combined-ca-bundle.pem -o rds-combined-ca-bundle.pem && curl https://cacerts.digicert.com/DigiCertGlobalRootG2.crt.pem -o DigiCertGlobalRootG2.crt.pem

and then in the second stage replace the
COPY --from=builder /app/certs/. /app/certs/ for COPY DigiCertGlobalRootG2.crt.pem rds-combined-ca-bundle.pem /app/certs/
and also
COPY --from=builder --chown=nobody /app/target/uberjar/metabase.jar /app/ for COPY --chown=nobody metabase.jar /app/

remember to have the run_metabase.sh file in the bin/docker/ path or change it to your current path

  1. then it's just about using docker build or docker buildx build to pass a --platform flag

@iwalucas
Copy link

iwalucas commented Oct 17, 2021

Great, tks! I pushed into docker hub a build under iwalucas/metabase, I copied the metabase from the latest instead of building it.....

@paoliniluis
Copy link
Author

Thanks @iwalucas, here you'll find a Dockerfile that will do the same:

FROM eclipse-temurin:11-jre-focal as runner

ENV FC_LANG en-US LC_CTYPE en_US.UTF-8

WORKDIR /app/

RUN apt-get update && apt-get upgrade -y && apt-get install -y --no-install-recommends ttf-dejavu && \
    # cleaning everything to reduce container size
    apt-get autoremove -y && apt-get autoclean && \
    rm -rf /var/lib/apt/lists/* && \
    # providing permissions to the nobody user
    curl https://downloads.metabase.com/latest/metabase.jar -o metabase.jar && \
    curl https://raw.githubusercontent.com/metabase/metabase/master/bin/docker/run_metabase.sh -o run_metabase.sh && \
    chmod +x run_metabase.sh && \
    chown -R nobody:nogroup /app

USER nobody

# expose our default runtime port
EXPOSE 3000

# run it
ENTRYPOINT ["/app/run_metabase.sh"]

with that Dockerfile, just do docker build . and you'll be good to go :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment