phoenixframework / tailwind

An installer for tailwind
MIT License
475 stars 61 forks source link

Tailwind binary not accessible during deploy #36

Closed fdeage closed 2 years ago

fdeage commented 2 years ago

I don't understand when the Tailwind binary is downloaded and installed in a prod environment.

I got this error during deploy:

Step 15/31 : COPY lib lib
 ---> cd38882bac8e
Step 16/31 : RUN npm run --prefix ./assets deploy
 ---> Running in 3abb3c2ba603

> deploy
> NODE_ENV=production tailwindcss --postcss --minify -i css/app.css -o ../priv/static/assets/app.css

sh: tailwindcss: not found
Error failed to fetch an image or build from source: error building: error rendering build status stream: The command '/bin/sh -c npm run --prefix ./assets deploy' returned a non-zero code: 127

And here is my Dockerfile, which comes straight from the Fly.io documentation:

# Using the Hex.pm docker images. You have much better version control for
# Elixir, Erlang and Alpine.
#
#   - https://hub.docker.com/r/hexpm/elixir/tags
#   - Ex: hexpm/elixir:1.11.2-erlang-23.3.2-alpine-3.13.3
#
# Debugging Notes:
#
#   docker run -it --rm hello_elixir /bin/ash

###
### Fist Stage - Building the Release
###
FROM hexpm/elixir:1.12.2-erlang-24.0.3-alpine-3.14.0 AS build

# install build dependencies
RUN apk add --no-cache build-base npm git

# prepare build dir
WORKDIR /app

# extend hex timeout
ENV HEX_HTTP_TIMEOUT=20

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

# set build ENV as prod
ENV MIX_ENV=prod
ENV SECRET_KEY_BASE=nokey

# Copy over the mix.exs and mix.lock files to load the dependencies. If those
# files don't change, then we don't keep re-fetching and rebuilding the deps.
COPY mix.exs mix.lock ./
COPY config config

RUN mix deps.get --only prod && \
    mix deps.compile

# install npm dependencies
COPY assets/package.json assets/package-lock.json ./assets/
RUN npm --prefix ./assets ci --progress=false --no-audit --loglevel=error

COPY priv priv
COPY assets assets

# NOTE: If using TailwindCSS, it uses a special "purge" step and that requires
# the code in `lib` to see what is being used. Uncomment that here before
# running the npm deploy script if that's the case.
COPY lib lib

# build assets
RUN npm run --prefix ./assets deploy
RUN mix phx.digest

# compile and build release
COPY rel rel
RUN mix do compile, release

###
### Second Stage - Setup the Runtime Environment
###

# prepare release docker image
FROM alpine:3.14.2 AS app

RUN apk add --no-cache libstdc++ openssl ncurses-libs imagemagick
RUN apk --no-cache add msttcorefonts-installer fontconfig && \
    update-ms-fonts && \
    fc-cache -f

WORKDIR /app

RUN chown nobody:nobody /app

USER nobody:nobody

COPY --from=build --chown=nobody:nobody /app/_build/prod/rel/my_app ./

ENV HOME=/app
ENV MIX_ENV=prod
ENV SECRET_KEY_BASE=nokey
ENV PORT=4000

CMD ["bin/my_app", "start"]

What am I missing here? Should I download the Tailwind binary separately?

chrismccord commented 2 years ago

Your mix file should have the assets.deploy alias:

  defp aliases do
    [
      setup: ["deps.get", "ecto.setup"],
      "ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"],
      "ecto.reset": ["ecto.drop", "ecto.setup"],
      test: ["ecto.create --quiet", "ecto.migrate --quiet", "test"],
      "assets.deploy": [
        "tailwind default --minify",
        "esbuild default --minify",
        "phx.digest"
      ]
    ]
  end

And your Dockerfile should call the deploy task before running mix compile:

# compile assets
RUN mix assets.deploy

RUN mix compile
fdeage commented 2 years ago

Thanks @chrismccord for your response.

I fail to understand, though, how running tailwind default --minify can... download and install tailwind somehow?

The only rule I have telling to install tailwind is in config/dev.exs: tailwind: {Tailwind, :install_and_run, [:default, ~w(--watch)]}

but there is nothing like that anywhere else :/

chrismccord commented 2 years ago

It installs it by default if it's not there :)

fdeage commented 2 years ago

OK, thanks!