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.
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.