Distillery issue with /priv when using Docker to build

Trying to use Distillery to create a better packaged container of super basic Cowboy/Plug app. I’ve been able to use MIX_ENV=prod mix distillery.release locally with no problems. But when I try to build with a container the priv/ directory isn’t getting my source priv/static/index.html content.

I’m trying to use the example here: https://hexdocs.pm/distillery/guides/working_with_docker.html but am stuck on getting this piece.

I’ve verified that the locally packaged tar.gz has my content, but the one built using the same exact command in the container does not. I’m probably missing something completely obvious, but am stumped. AFAICT all the versions are the same - I mean mix deps.get is run in both places.

Any ideas?

Here’s my Dockerfile:

# The version of Alpine to use for the final image
# This should match the version of Alpine that the `elixir:1.7.2-alpine` image uses
ARG ALPINE_VERSION=3.10

FROM elixir:1.9.4-alpine AS builder

# The following are build arguments used to change variable parts of the image.
# The name of your application/release (required)
ARG APP_NAME
# The version of the application we are building (required)
ARG APP_VSN
# The environment to build with
ARG MIX_ENV=prod
# Set this to true if this release is not a Phoenix app
ARG SKIP_PHOENIX=true
# If you are using an umbrella project, you can change this
# argument to the directory the Phoenix app is in so that the assets
# can be built
ARG PHOENIX_SUBDIR=.

ENV SKIP_PHOENIX=${SKIP_PHOENIX} \
    APP_NAME=${APP_NAME} \
    APP_VSN=${APP_VSN} \
    MIX_ENV=${MIX_ENV}

# By convention, /opt is typically used for applications
WORKDIR /opt/app

# This step installs all the build tools we'll need
RUN apk update && \
  apk upgrade --no-cache && \
  apk add --no-cache \
    git \
    build-base && \
  mix local.rebar --force && \
  mix local.hex --force

# This copies our app source code into the build container
COPY . .

RUN mix do deps.get, deps.compile, compile

# This step builds assets for the Phoenix app (if there is one)
# If you aren't building a Phoenix app, pass `--build-arg SKIP_PHOENIX=true`
# This is mostly here for demonstration purposes
RUN if [ ! "$SKIP_PHOENIX" = "true" ]; then \
  cd ${PHOENIX_SUBDIR}/assets && \
  yarn install && \
  yarn deploy && \
  cd - && \
  mix phx.digest; \
fi

RUN \
  mkdir -p /opt/built && \
  MIX_ENV=${MIX_ENV} mix distillery.release --verbose --env=prod && \
  cp _build/${MIX_ENV}/rel/${APP_NAME}/releases/${APP_VSN}/${APP_NAME}.tar.gz /opt/built && \
  cd /opt/built && \
  tar tvf ${APP_NAME}.tar.gz && \
  tar -xvzf ${APP_NAME}.tar.gz && \
  rm ${APP_NAME}.tar.gz

# From this line onwards, we're in a new image, which will be the image used in production
FROM alpine:${ALPINE_VERSION}

# The name of your application/release (required)
ARG APP_NAME

RUN apk update && \
    apk add --no-cache \
      bash \
      git \
      openssl-dev

ENV REPLACE_OS_VARS=true \
    APP_NAME=${APP_NAME}

WORKDIR /opt/app

COPY --from=builder /opt/built .

CMD trap 'exit' INT; /opt/app/bin/${APP_NAME} foreground

does your yarn deploy put that index.html in /priv/static?

/priv/static is usually in your .gitignore and so you can you cannot simply place files there…

most likely you need to update your webpack.config.js to output that index.html to /priv/static or simply use a cp in your docker script (before mix.digest) eg:

cp ${PHOENIX_SUBDIR}/assets/index.html ${PHOENIX_SUBDIR}/priv/static/index.html

but honestly it’s a bit “weird” having index.html in there since it “should” be handled by a phoenix controller… what is the purpose/content of index.html?

Thanks for the reply. This isn’t a phoenix app…just Cowboy and Plug - no Phoenix needed here.

Here’s my mix.exs:

defp deps do
    [
      {:plug, "~> 1.6"},
      {:cowboy, "~> 2.4"},
      {:plug_cowboy, "~> 2.0"},
      {:credo, "~> 0.10", except: :prod, runtime: false},
      {:redix, ">= 0.0.0"},
      ...
      {:distillery, "~> 2.1"}
    ]
  end

And like I said in the original post, the Distillery mix distillery.release works when I run it directly from macOS. The issue is when this command is run from inside the container.

ahh my bad - missed the ARG SKIP_PHOENIX=true

remove priv/static/ from your .dockerignore and you should be good to go…

Ah schnit! That’s it…completely forgot about that thing. Much appreciation @outlog.

1 Like