Can't install Chrome / Chromium via Dockerfile or SSH

Hey all!
I’m developing a Phoenix app that generates PDFs using headless Chrome via ChromicPDF. It works flawlessly on localhost. But when deploying to Fly.io I keep running into issues installing Chrome.

I’ve tried installing Chrome via my app’s Dockerfile to the RUNNER_IMAGE:

RUN apt-get update -y && apt-get install -y libstdc++6 openssl libncurses5 locales curl
RUN curl -LO https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
RUN apt-get install -y ./google-chrome-stable_current_amd64.deb
RUN rm google-chrome-stable_current_amd64.deb 

And via SSH. While installing via SSH apt-get install always seems to get stuck at some point.

flyctl ssh console
apt-get update 
apt-get install curl
curl -LO https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
apt-get install ./google-chrome-stable_current_amd64.deb

In the end whereis google-chrome returns nothing and my application can’t find the executable.
I’ve tried the above with Chromium as well.

If Chrome or Chromium is installed ChromicPDF should be able to pick up the executable.

Any help is appreciated!

I wasn’t able to reproduce this. Can you share the app name?

https://silent-sea-354.fly.dev/

As soon as you click on anything (e.g. Log in) ChromicPDF crashes.

Can you post the entire Dockerfile?

Not answering the question, but just saying that it might be good idea to separate html->pdf generation to another app.

That way you can e.g. scale that independently.

Definitely a good point, @savikko . For now I’m just trying to get a version deployed to play around with though.

@jsierles I’ve figured it out. I’ve created a minimal example, just to make sure it’s not caused by anything else. Chrome is being installed correctly and whereis google-chrome returns the correct path (/usr/bin/google-chrome; not sure what I did wrong before…). But somehow ChromicPDF doesn’t find the executable on the Fly.io machine. Setting chrome_executable: "/usr/bin/google-chrome" in the ChromicPDF options fixes the issue.
Thanks a lot for your help!

Just for reference, here’s the Dockerfile:

# Find eligible builder and runner images on Docker Hub. We use Ubuntu/Debian instead of
# Alpine to avoid DNS resolution issues in production.
#
# https://hub.docker.com/r/hexpm/elixir/tags?page=1&name=ubuntu
# https://hub.docker.com/_/ubuntu?tab=tags
#
#
# This file is based on these images:
#
#   - https://hub.docker.com/r/hexpm/elixir/tags - for the build image
#   - https://hub.docker.com/_/debian?tab=tags&page=1&name=bullseye-20210902-slim - for the release image
#   - https://pkgs.org/ - resource for finding needed packages
#   - Ex: hexpm/elixir:1.13.1-erlang-24.2-debian-bullseye-20210902-slim
#
ARG ELIXIR_VERSION=1.13.1
ARG OTP_VERSION=24.2
ARG DEBIAN_VERSION=bullseye-20210902-slim

ARG BUILDER_IMAGE="hexpm/elixir:${ELIXIR_VERSION}-erlang-${OTP_VERSION}-debian-${DEBIAN_VERSION}"
ARG RUNNER_IMAGE="debian:${DEBIAN_VERSION}"

FROM ${BUILDER_IMAGE} as builder

# install build dependencies
RUN apt-get update -y && apt-get install -y build-essential git \
  && apt-get clean && rm -f /var/lib/apt/lists/*_*

# prepare build dir
WORKDIR /app

# install hex + rebar
RUN mix local.hex --force && \
  mix local.rebar --force

# set build ENV
ENV MIX_ENV="prod"

# install mix dependencies
COPY mix.exs mix.lock ./
RUN mix deps.get --only $MIX_ENV
RUN mkdir config

# copy compile-time config files before we compile dependencies
# to ensure any relevant config change will trigger the dependencies
# to be re-compiled.
COPY config/config.exs config/${MIX_ENV}.exs config/
RUN mix deps.compile

COPY priv priv

COPY lib lib

COPY assets assets

# compile assets
RUN mix assets.deploy

# Compile the release
RUN mix compile

# Changes to config/runtime.exs don't require recompiling the code
COPY config/runtime.exs config/

COPY rel rel
RUN mix release

# start a new build stage so that the final image will only contain
# the compiled release and other runtime necessities
FROM ${RUNNER_IMAGE}

RUN apt-get update -y && apt-get install -y curl
RUN curl -LO https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb

RUN apt-get install -y libstdc++6 openssl libncurses5 locales ./google-chrome-stable_current_amd64.deb \
  && apt-get clean && rm -f /var/lib/apt/lists/*_* ./google-chrome-stable_current_amd64.deb

# RUN apt-get install -y ./google-chrome-stable_current_amd64.deb

# Set the locale
RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && locale-gen

ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
ENV LC_ALL en_US.UTF-8

WORKDIR "/app"
RUN chown nobody /app

# set runner ENV
ENV MIX_ENV="prod"

# Only copy the final release from the build stage
COPY --from=builder --chown=nobody:root /app/_build/${MIX_ENV}/rel/demo ./

USER nobody

CMD ["/app/bin/server"]
# Appended by flyctl
ENV ECTO_IPV6 true
ENV ERL_AFLAGS "-proto_dist inet6_tcp"

UPDATE: While this did work for the stripped-down example project, with my “real” app I kept running into out-of-memory issues. I assume that my other dependencies consumed a fair bit of RAM. So there is still some room for optimization - For now scaling VM memory to 1GB fixes the issue.