如何解决Rust Axum应用通过Docker Compose传递环境变量失败问题
问题
我有一个Rust Axum应用,启动初期会读取数据库URL创建数据库连接,代码如下:
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");
目前遇到的问题是:应用无法获取环境变量,db_connection_str为空,控制台输出“Connecting to database: ”,看不到实际的数据库URL。
我的Dockerfile内容:
FROM rust:1.84 AS development WORKDIR /backend COPY . . ARG DATABASE_URL ENV DATABASE_URL=$DATABASE_URL RUN cargo run
Docker Compose配置:
backend: build: ./backend ports: - "5173:5173" environment: DATABASE_URL: $DATABASE_URL
我有一个.env文件用于存储环境变量。
注意:执行以下命令时,应用能正常获取环境变量:
docker build -t backend --build-arg DATABASE_URL=<Database_url> .
但执行docker-compose up时就会出现上述无法获取环境变量的问题。
解决方案
核心问题分析
- Dockerfile逻辑错误:旧Dockerfile里的
RUN cargo run是在镜像构建阶段执行的,而Docker Compose中environment配置的是容器运行阶段的环境变量,构建阶段根本拿不到这些变量。另外,把应用运行放在构建步骤里本身就不符合Docker最佳实践——构建阶段应只负责编译代码,运行操作要放在容器启动时执行。 - Compose环境变量传递方式问题:旧配置里
DATABASE_URL: $DATABASE_URL需要确保Compose能正确读取本地.env文件的变量,否则会传递空值。
具体修复步骤
1. 重构Dockerfile,分离构建与运行阶段
修改Dockerfile,先在构建阶段编译二进制文件,再在运行阶段复制产物并启动应用:
# 构建阶段:编译Rust应用 FROM rust:1.84 AS builder WORKDIR /backend COPY . . # 编译release版本(需要debug版本则替换为cargo build) RUN cargo build --release # 运行阶段:只保留必要的运行环境和二进制文件 FROM rust:1.84 AS development WORKDIR /backend # 从构建阶段复制编译好的二进制文件(替换为你Cargo.toml里的项目名称) COPY --from=builder /backend/target/release/your-app-name . # 容器启动时运行应用 CMD ["./your-app-name"]
2. 调整Docker Compose配置
让Compose正确读取.env文件并传递环境变量到容器运行阶段:
backend: build: ./backend ports: - "5173:5173" # 直接指定要传递的环境变量名,Compose会自动从当前目录的.env文件中读取对应值 environment: - DATABASE_URL # 如果你的.env文件不在Compose文件同级目录,可手动指定路径 # env_file: # - ./path/to/your/.env
3. 检查.env文件格式
确保.env文件无多余空格,格式正确:
DATABASE_URL=postgres://username:password@db-host:5432/db-name
为什么单独构建命令能生效?
因为手动执行docker build时,通过--build-arg DATABASE_URL把变量传递给了构建阶段,而旧Dockerfile里的RUN cargo run正好在构建阶段执行,所以能拿到这个变量。但Compose的environment是给运行阶段的,旧Dockerfile的运行逻辑在构建阶段,自然拿不到。
内容的提问来源于stack exchange,提问作者Kadiem Alqazzaz
相关产品推荐
相关产品推荐

