Docker部署Rust Actix服务出现404错误的排查求助
我在Docker中部署基于Rust Actix框架开发的Web服务时出现404错误,但本地运行该服务一切正常。近2-3天来仅在Docker环境中出现此问题,其他容器运行均正常。执行sudo docker compose up时仅出现一条my-app警告,构建完成。以下是相关配置及代码,恳请帮忙排查问题:
Dockerfile
# Build stage FROM rust:slim-buster as builder RUN apt-get update && \ apt-get install -y pkg-config make g++ libssl-dev cmake libmariadb-dev-compat openssl && \ rustup target add x86_64-unknown-linux-gnu WORKDIR /var/www/app COPY . . RUN cargo build # Prod stage, removing the Rust toolchain FROM gcr.io/distroless/cc COPY --from=builder /var/www/app/config /config COPY --from=builder /var/www/app/target/debug/my-app / CMD ["./my-app"]
docker-compose.yml
version: '3.9' services: my-app: container_name: my-app image: my-app build: . ports: - '8088:8088' expose: - '8088' depends_on: - redis - mosquitto - db redis: container_name: redis image: "redis:latest" ports: - "6379:6379" expose: - "6379" mosquitto: image: eclipse-mosquitto:2.0.15 container_name: mosquitto user: mosquitto volumes: - type: bind source: ./config/ target: /mosquitto/config/ # - type: bind # source: ./log/ # target: /mosquitto/log/ - type: volume source: data target: /mosquitto/data ports: - target: 1883 published: 1883 protocol: tcp mode: host - target: 9001 published: 9001 protocol: tcp mode: host db: container_name: sqlite3 image: nouchka/sqlite3:latest stdin_open: true tty: true volumes: #Modify following line - ./config/isumis.db:/config ports: - '9000:9000' # expose ports - HOST:CONTAINER expose: - '9000' restart: unless-stopped mobsf: container_name: mobsf build: https://github.com/MobSF/Mobile-Security-Framework-MobSF.git image: mobsf ports: - "8000:8000" expose: - "8000" nodejs: container_name: blacklight-collector image: isumis/blacklight build: context: ./blacklight-config/ ports: - "8081:8081" expose: - "8081" volumes: data: name: "mqtt-broker-data"
Actix服务代码
pub async fn server() -> Result<(), impl Error> { info!("Start backend!"); init(); let store: Data<DataStore> = Data::new(DataStore::default()); info!("Swagger UI available at http://localhost:8088/api/ and http://localhost:8088/clm-core/"); // Init actix HttpServer::new(move || { App::new() .wrap(Logger::default()) .configure(data_controller::configure(store.clone())) .service( SwaggerUi::new("/api/{_:.*}") .url("/api-docs/openapi.json", ApiDoc::openapi().clone()), ) .service( SwaggerUi::new("/clm-core/{_:.*}") .external_url_unchecked("http://localhost:3006/core/swagger", json!({"openapi": "3.0.0"})), ) .service( web::scope("/dashboard/user") .service(get_user_by_id) //.service(get_user_data) ) .service( web::scope("/dashboard") .service(get_all_statistics) //.service(get_specific_statistics) .service(static_scan) ) .service( web::scope("/tools") .service(blacklight) .service(port_scanner) .service(analyze_ip) ) .service( web::scope("/init") .service(create_test_user) .service(api_key) ) }) .bind(("0.0.0.0", 8088))? .run() .await } fn init() { // Connect to redis redis_service::init(); thread::spawn(|| { // Wait for new messages crate::service::subscriber_service::subscriber(); }); }
依赖配置
bench = [] test = [] example = [] [[bin]] path = "src/main.rs" name = "my-app" test = false doctest = false bench = false doc = false plugin = false proc-macro = false harness = true edition = "2021" required-features = [] [package] name = "my-app" edition = "2021" version = "0.0.1" autobins = false autoexamples = false autotests = false autobenches = false [profile.release] lto = true opt-level = "z" debug = true strip = true [profile.dev] debug = 2 [dependencies] actix-web = "4" async-std = "1.12.0" cfonts = "1" futures = "*" isocountry = "0.3.2" lazy_static = "*" log = "0.4" paho-mqtt = "0.12.1" r2d2 = "0.8.10" regex = "1" serde_json = "1" simple_logger = "*" whois-rust = "1.5.1" rand = "0.8.5" dns-lookup = "2.0.2" [dependencies.attohttpc] version = "0.26.0" features = ["json"] [dependencies.redis] version = "0.23.1" features = ["r2d2"] [dependencies.serde] version = "1.0" features = ["derive"] [dependencies.utoipa] version = "3.4.4" features = ["actix_extras"] [dependencies.utoipa-swagger-ui] version = "3.1.5" features = ["actix-web"]
启动时的警告信息
[+] Running 1/1 ! my-app Warning 1.5s [+] Building 93.0s (14/14) FINISHED
排查方向及解决方案
镜像构建优化
当前Dockerfile构建的是debug版本,拷贝的是target/debug/my-app。debug版本可能存在路径依赖或动态库缺失问题,建议切换为release版本:
修改Dockerfile中的构建命令为RUN cargo build --release,同时将拷贝路径改为/var/www/app/target/release/my-app。distroless镜像精简,release版本对依赖的要求更低,更适合生产环境。端口与网络验证
- 进入容器检查服务监听状态:如果distroless镜像缺少
netstat,可临时替换为ubuntu:latest镜像调试,执行netstat -tulpn确认服务绑定0.0.0.0:8088。 - 宿主机执行
netstat -tulpn | grep 8088,确认端口映射已生效。
- 进入容器检查服务监听状态:如果distroless镜像缺少
配置文件校验
进入容器执行ls /config,确认配置文件完整且权限正常。检查服务代码中读取配置的路径是否指向容器内的/config,避免本地相对路径在容器内失效。依赖服务就绪问题
depends_on仅保证容器启动顺序,不保证服务就绪。Redis、DB等服务可能未完全启动导致Actix初始化失败,路由未注册:
在docker-compose.yml的my-app服务中添加健康检查,等待服务就绪:healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8088/init/api_key"] interval: 10s timeout: 5s retries: 3 start_period: 30s日志分析
执行docker logs my-app查看服务启动日志,检查是否存在Redis连接失败、数据库加载错误等初始化异常,这些问题会导致路由未正确注册从而返回404。同时可升级Actix日志级别,添加详细请求日志,确认请求路径是否匹配路由规则。
内容的提问来源于stack exchange,提问作者Jan

