skip to Main Content

I’m writing a rest api in Rust, and I’m connecting it to Firestore. I set up default application credentials via the gcloud cli and when running it locally (whether via cargo run or via executing the release binary), it connects to Firestore just fine and can read and write data.

However, the problem begins as soon as it is dockerized. I deployed it to Cloud Run but it fails when creating the Firestore client:

#[tokio::main]
async fn main() -> Result<(), anyhow::Error> {
    let db = create_firestore_db().await?;

    // ...
}

async fn create_firestore_db() -> anyhow::Result<FirestoreDb> {
    let project_id = get_project_id()?;
    FirestoreDb::new(project_id)
        .await
        .map_err(|e| anyhow::anyhow!("Failed to create FirestoreDb: {}", e))
}

fn get_project_id() -> anyhow::Result<String> {
    std::env::var("PROJECT_ID").map_err(|e| anyhow::anyhow!("Failed to find PROJECT_ID: {}", e))
}

The message I get is

Error: Failed to create FirestoreDb: Firestore system/internal error: GCloud system error: Tonic/gRPC error: transport error

I get the very same error if I run the container locally. At first I thought it might be the case that (somehow) the container can’t reach the internet, but running a shell in the container, installing inetutils, and pinging google works just fine.

I thought it might be an issue with the base image: I tried debian bullseye and its slim version, as well as doing away with the multi-stage dockerfile and just trying cargo run instead of installing it.

I don’t think it’s auth issue because the message is saying that it’s a transport error, which AFAICT basically means that the destination server closed the connection?

Trying to Google this issue in the context of docker is frustrating, since all the results are about docker’s network mode (which made no difference to my issue) or some other docker configuration issue. I’ve written node and go services that run on cloud run and connect to firestore and I’ve never had this issue pop up.

For extra context, the spec for firestore in my Cargo.toml is firestore = "0.32.2" and my Dockerfile looks like this:

FROM rust:1.67 as builder

WORKDIR /usr/src/my-rest-api

COPY . .

RUN cargo install --path my-cargo-workspace-binary-project

# ---

FROM debian:bullseye-slim

COPY --from=builder /usr/local/cargo/bin/my-rest-api /usr/local/bin/my-rest-api

CMD ["my-rest-api"]

I’d be very grateful to hear if anyone else has come across this issue and how they’ve conquered it.

2

Answers


  1. I had exactly the same issue with also trying to deploy a rust based project with firestore deployed on cloud run.

    I iterated multiple times. Until I ended up finding a suitable Dockerfile.

    I don’t have a real understanding about why it worked for me.

    FROM rust:1.70.0-bullseye as builder
    
    WORKDIR /usr/src/my-rest-api
    RUN DEBIAN_FRONTEND=noninteractive apt -qq update &&
        DEBIAN_FRONTEND=noninteractive apt -qq install -y libssl-dev
    COPY . .
    
    RUN cargo install --path my-cargo-workspace-binary-project
    
    # ---
    
    FROM rust:1.70.0-bullseye
    
    COPY --from=builder /usr/local/cargo/bin/my-rest-api /usr/local/bin/my-rest-api
    
    CMD ["my-rest-api"]
    

    hopefully, you’ll find this useful.

    Login or Signup to reply.
  2. Disclaimer: Author of the crate firestore.

    The common issue when this happens is that docker images are built without CA roots inside, meaning all TLS connections may actually fail (not just calls to Google APIs).

    So, to fix it you need to install CA root certificates when you build your image.

    For Debian-based images it usually this command:

    RUN apt-get install -y ca-certificates
    

    Or you can use Google Distroless which already contains CA root certs, more secure and small.

    Other reports and docker examples:

    Hope this helps.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search