Skip to content

Error in compiling elixir projects in multi-user dockerfile #14797

@la-j

Description

@la-j

Elixir and Erlang/OTP versions

Erlang/OTP 27 [erts-15.2.7.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns]

Elixir 1.18.4 (compiled with Erlang/OTP 27)

Operating system

Hexpm elixir alpine, debian and ubuntu

Current behavior

Steps to reproduce:

  1. Create an elixir project
mix new compile_lock_error
cd compile_lock_error
  1. Create .dockerignore and Dockerfile:
/_build/
/deps/
FROM hexpm/elixir:1.18.4-erlang-27.3.4.3-debian-bookworm-20250908-slim

WORKDIR /app
COPY . .
RUN mix compile

RUN adduser user
USER user
  1. Build and run the image with the compile command:
docker build -t compile_lock_error .
docker run --rm -it compile_lock_error mix compile
07:31:09.903 [error] GenServer Mix.Sync.PubSub terminating
** (File.Error) could not touch "/tmp/mix_pubsub_ZGVmYXVsdA/PLG7-rLl0Fbg6k7k93nhKg/port_54485": permission denied
    (elixir 1.18.4) lib/file.ex:632: File.touch!/2
    (mix 1.18.4) lib/mix/sync/pubsub.ex:142: Mix.Sync.PubSub.handle_call/3
    (stdlib 6.2.2.2) gen_server.erl:2381: :gen_server.try_handle_call/4
    (stdlib 6.2.2.2) gen_server.erl:2410: :gen_server.handle_msg/6
    (stdlib 6.2.2.2) proc_lib.erl:329: :proc_lib.init_p_do_apply/3
Last message (from Mix.PubSub.Subscriber): {:subscribe, #PID<0.111.0>, "/app/_build/prod"}
State: %{port: nil, hash_to_pids: %{}}
Client Mix.PubSub.Subscriber is alive

    (stdlib 6.2.2.2) gen.erl:241: :gen.do_call/4
    (elixir 1.18.4) lib/gen_server.ex:1125: GenServer.call/3
    (mix 1.18.4) lib/mix/sync/pubsub.ex:44: Mix.Sync.PubSub.subscribe/1
    (mix 1.18.4) lib/mix/pubsub/subscriber.ex:21: Mix.PubSub.Subscriber.init/1
    (stdlib 6.2.2.2) gen_server.erl:2229: :gen_server.init_it/2
    (stdlib 6.2.2.2) gen_server.erl:2184: :gen_server.init_it/6
    (stdlib 6.2.2.2) proc_lib.erl:329: :proc_lib.init_p_do_apply/3

07:31:09.925 [notice] Application mix exited: shutdown
** (ArgumentError) errors were found at the given arguments:

  * 1st argument: the table identifier does not refer to an existing ETS table

    (stdlib 6.2.2.2) :ets.lookup(Mix.State, :debug)
    (mix 1.18.4) lib/mix/state.ex:26: Mix.State.get/2
    (mix 1.18.4) lib/mix/cli.ex:112: Mix.CLI.run_task/2
    /usr/local/bin/mix:2: (file)

Expected behavior

There should not be any errors since the original user and the new user shouldn't share the same compile lock.

It seems that we're using the USER env in the build lock mechanism:

https://github.com/elixir-lang/elixir/blob/v1.18.4/lib/mix/lib/mix/sync/lock.ex#L124

  defp base_path do
    # We include user in the dir to avoid permission conflicts across users
    user = System.get_env("USER", "default")
    Path.join(System.tmp_dir!(), "mix_lock_#{Base.url_encode64(user, padding: false)}")
  end

All of the major containers don't use the USER env to indicate the current user

Repos/tests/compile_lock_error > docker run --rm -it debian env     
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=060b5f1efe1c
TERM=xterm
HOME=/root
Repos/tests/compile_lock_error > docker run --rm -it ubuntu env 
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=8373aa20118e
TERM=xterm
HOME=/root
Repos/tests/compile_lock_error > docker run --rm -it alpine env 
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=b94530ee444d
TERM=xterm
HOME=/root

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions