H12

H12

So I’m working on docker-izing a LiveView side-project of mine, and I’m having some struggles with code reloading.

Specifically, when I make changes to a LiveView project file, the app simply won’t recompile, throwing the following error:

** (RuntimeError) could not compile application: docker_example.

You must restart your server after changing the following config or lib files:

  * config/dev.exs
  * config/config.exs
  * mix.exs


    (phoenix 1.5.4) lib/phoenix/code_reloader/server.ex:211: Phoenix.CodeReloader.Server.mix_compile_unless_stale_config/1
    (phoenix 1.5.4) lib/phoenix/code_reloader/server.ex:196: Phoenix.CodeReloader.Server.mix_compile_project/3
    (phoenix 1.5.4) lib/phoenix/code_reloader/server.ex:75: anonymous fn/2 in Phoenix.CodeReloader.Server.handle_call/3
    (phoenix 1.5.4) lib/phoenix/code_reloader/server.ex:262: Phoenix.CodeReloader.Server.proxy_io/1
    (phoenix 1.5.4) lib/phoenix/code_reloader/server.ex:73: Phoenix.CodeReloader.Server.handle_call/3
    (stdlib 3.12.1) gen_server.erl:661: :gen_server.try_handle_call/4
    (stdlib 3.12.1) gen_server.erl:690: :gen_server.handle_msg/6
    (stdlib 3.12.1) proc_lib.erl:249: :proc_lib.init_p_do_apply/3

I’ve been able to reproduce this in a fresh mix phx.new app_name --live --no-ecto project using the following files:

Dockerfile

FROM elixir:1.10

RUN apt-get update
RUN apt-get install --yes build-essential inotify-tools

# Set working directory
WORKDIR /app

# Install hex and rebar
RUN mix local.hex --force &&\
      mix local.rebar --force

# Install nodejs
RUN curl -sL https://deb.nodesource.com/setup_12.x | bash - &&\
      apt-get install --yes nodejs

# Set the run command
CMD ["./run.sh"]

run.sh

#!/bin/sh

echo "Installing Elixir dependencies...\n"
mix deps.get
mix deps.compile

echo "Installing Node dependencies...\n"
cd assets && npm install
cd ..

echo "Launching Phoenix server...\n"
mix phx.server

docker-compose.yml

services:
  app:
    build: .
    ports:
      - "4000:4000"
    volumes:
      - /app/_build
      - /app/deps
      - /app/priv
      - /app/assets/node_modules
      - .:/app

With those files added to the project root, and after starting the project with docker-compose up --build, making a change to the generated lib/docker_example_web/live/page_live.ex file usually results in a compilation error. It sometimes reloads as it should, but I’m generally able to get it to fail compilation after saving a couple of times.

Additionally, when serving the app with mix phx.server, code reloading works flawlessly, so I’m fairly confident this issue is Docker-related.

Anyone have any idea what’s going on here? I’ve thrown a ton of different Dockerfile & docker-compose.yml setups at this problem to no avail.

Showing Posts 1 to 10

slouchpie

slouchpie

Your given code does not even run for me. I get permission denied error when container tries to run run.sh.

Your general approach seems a bit wrong. There should be a COPY statement somewhere in your Dockerfile. Also you should mix deps.get and mix deps.compile as part of the build.

Try this setup:

Dockerfile:

FROM elixir:1.10

RUN curl -sL https://deb.nodesource.com/setup_12.x | bash -
RUN apt update
RUN apt install -y git nodejs inotify-tools
RUN apt install -y chromium-driver

RUN mkdir -p /app
WORKDIR /app

RUN mix local.hex --force && \
  mix local.rebar --force && \
  mix archive.install --force hex phx_new

COPY mix.exs .
COPY mix.lock .

# copy the deps in dev environment for faster builds
COPY deps ./deps
RUN ["mix", "deps.get"]
RUN ["mix", "deps.compile"]

COPY assets ./assets
WORKDIR /app/assets
RUN ["npm", "install"]

WORKDIR /app

COPY config ./config
COPY lib ./lib
COPY seeds ./seeds
COPY priv ./priv
COPY test ./test
COPY dev/support ./dev/support

RUN ["mix", "compile"]

# compile deps in test environment for faster test runs when built
RUN export MIX_ENV=test && mix deps.compile

COPY ./run.sh ./run.sh
CMD ["/bin/bash", "entrypoint.sh"]

with a run.sh like this:

iex --sname app -S mix phx.server;

and a docker-compose.yml like this:

version: "3.8"
services:
  app:
    image: app:local
    build:
      context: .
      dockerfile: ./Dockerfile
    ports:
      - "4000:4000"
    volumes:
      - /app/assets/node_modules
      - ./assets:/app/assets:ro
      - ./config:/app/config:ro
      - ./lib:/app/lib:ro
      - ./priv:/app/priv
      - ./test:/app/test:ro
      - ./seeds:/app/seeds:ro
      - ./mix.exs:/app/mix.exs:ro
      - ./run.sh:/app/run.sh:ro
    stdin_open: true
    tty: true

I don’t know why your setup had the problem with config or mix.exs being “altered” but I suspect it has something to do with how your never actually COPY the files during your build.

Disclaimer: there is no one correct way to use docker. It depends on your own needs. What I have provided is good for local :dev environment, local debugging.

Exadra37

Exadra37

For development never use the COPY or ADD command in your Dockerfile, just map the the required folders in docker-compose.yml file. Also using using version 3.* in docker compose is only necessary if your are running the application in a docker swarm, otherwise just stick with the normal 2.* version that are more suitable for normal docker flow in development.

slouchpie

slouchpie

Why should you not COPY the files when building in dev?

Exadra37

Exadra37

Because you then need to rebuild the container each time you change a file, while mapping them in docker-compose.yml always reflects immediately in the docker container the changes done in host.

slouchpie

slouchpie

But if you mount them as volumes, like I did above, then the changes are reflected. You don’t have to rebuild the image.

Exadra37

Exadra37

So why are you then COPY them inside the container?

slouchpie

slouchpie

So I don’t have to build every time I run the container. With my approach, your built image has all the deps compiled and the code from the time you built the image. The dev can add new deps and edit the code and still use the same image because the volume mounting will change what is necessary. Note how I use ro with the volume mounting to get read-only access, so container cannot edit source code.

Exadra37

Exadra37

I don’t have to build every time I run the docker container, because I map the entire app I am working on to the container, thus I have the exact same dev flow I would have if I was not using docker.

Exadra37

Exadra37

I think that at this point you need to run the docker build command again.

slouchpie

slouchpie

Sure, if the deps are new, then you would have to rebuild. But what I look for is the smallest possible "boot"time. I don’t want anything being compiled or fetched just because I docker-compose down to go to the shop for 10 minutes. How often do you actually add/remove new deps when developing? Not even once per day, on average? If you don’t COPY anything during build phase then every time you spin up a new container, you have to fetch and compile all deps and compile the app? That seems like inefficient dev workflow to me. I would rather be able to spin up a new container in 5 seconds. I don’t mind rebuilding for new deps. That is a fair price for me.

Like I said, I think there are different approaches for using docker in dev environment.I don’t think there is one true way. I also don’t think it’s good to have absolute rules such as “never use the COPY…command…[for development]”.

Where Next? Top

Trending in Questions Top

stjefim
Hello! Suppose you are building workflow (order / task / payment) processing system with the following requirements: Each workflow con...
New
jonnycharles
I’m in search of an Elixir library that offers PDF generation capabilities similar to Ruby’s Prawn. While there have been discussions abo...
New
spammy
I’m looking to build a personal workflow to quickly deploy web applications written in elixir/phoenix, for local consumption (ie not on t...
New
Blokh
Hey guys, I’ve got a huge CSV ( around 10 GB ) that needs to be processed hourly Do you guys have any suggestions what is the best prac...
New
dli
Before I dive in myself, did anyone successfully sprinkle Hologram into their existing LiveView app? Looking for hints regarding: Addi...
New
roeland
Kia ora, We have been using elixir-google-api to connect to Google Drive. However, with the updates to Tesla due to CVEs this is now bro...
New
bottlenecked
Hi all, I wanted to ask how the community is dealing with post-release steps. Today we have Ecto migrations, which make sure that the db...
New

Other Trending Topics Top

JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve. They are GUI (Emerge) and State management (S...
New
ausimian
Emily is an Elixir library that runs Nx computations on Apple’s MLX. Install it as the default Nx backend and Nx, defn, Axon, Nx.Serving,...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews