Search code examples
dockerrustdocker-composedockerfile

How to pass Environment Variables from docker compose


I have a rust Axum application that reads database URL at the very beginning to create database connection:

async fn main() {
    let db_connection_str = std::env::var("DATABASE_URL").expect("DATABASE_URL must be set.");
    println!("Connecting to database: {}", db_connection_str);


    let pool = PgPoolOptions::new()
       .max_connections(5)
       .acquire_timeout(Duration::from_secs(3))
       .connect(&db_connection_str)
       .await
       .expect("can't connect to database");

The issue is that its not getting the environment variable. db_connection_str is empty, and I get this println in the console "Connecting to database: " without the actual value.

this is dockerfile

FROM rust:1.84 AS development

WORKDIR /backend

COPY . .

ARG DATABASE_URL
ENV DATABASE_URL=$DATABASE_URL

RUN cargo run

And here is the docker-compose file

  backend:
    build: ./backend
    ports:
      - "5173:5173"
    environment:
      DATABASE_URL: $DATABASE_URL

I have a .env file for environment variables.

Note: When I run this command

docker build -t backend --build-arg DATABASE_URL=<Database_url> .

it works, it gets the environment variable, but when I run docker-compose up it does not, and the issue mentioned above happens.


Solution

  • You don't specify a command to run at run-time.

    Your RUN cargo run is run at build time and that seems wrong. It should be something like CMD cargo run instead, so it would run at run-time. Try this:

    FROM rust:1.84 AS development
    
    WORKDIR /backend
    
    COPY . .
    
    ARG DATABASE_URL
    ENV DATABASE_URL=$DATABASE_URL
    
    CMD cargo run
    

    Building an image is like compiling a Rust program. Running the container is like running the compiled executable.

    RUN statements are run at build time, so your cargo run command was run during docker build where networking, environment variables, volumes etc. are not set up. Those are set up at run time.

    CMD (and ENTRYPOINT) statements tell Docker what command should be run when the container is run. At run-time the environment variables are set up, and your program runs.