I’m currently working with two Docker containers: one running an Actix server and the other running a frontend application (framesurge-perseus). The Actix server binds to a Unix Domain Socket (UDS) at /tmp/iso-uds.socket. I’ve created a shared volume for this socket, which I’ve successfully accessed and tested from a different container using netcat.
However, I’m encountering an issue when the frontend container tries to fetch data from the shared volume inside the docker container. Specifically, it throws the following error:
Running `dist/target_engine/release/front`
451.5 Error: render function 'build_state' in template '' failed (cause: Server(None))
451.5
451.5 Caused by:
451.5 Hyper error: Hyper error: error trying to connect: No such file or directory (os error 2)
------
failed to solve: process "/bin/sh -c perseus deploy" did not complete successfully: exit code: 1
Here’s the relevant code that fetches data from the server via the socket path which returned an error:
use hyper::{body::HttpBody, Client};
use hyperlocal::{UnixClientExt, Uri};
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use tokio::io::{self, AsyncWrite as _};
use perseus::prelude::*;
use std::io::stdout;
use std::error::Error;
pub static SOCKET_ADDR: &str = "/tmp/iso-uds.socket";
#[cfg(engine)]
pub async fn client_request<T: DeserializeOwned>(path: String) -> Result<T, hyper::Error> {
use crate::SOCKET_ADDR;
use hyper::body::HttpBody;
use hyperlocal::UnixClientExt;
let url = hyperlocal::Uri::new(SOCKET_ADDR, &path).into();
let client = hyper::Client::unix();
let mut response = client.get(url).await?;
let mut bytes = Vec::default();
while let Some(next) = response.data().await {
let chunk = next?;
bytes.extend(chunk);
}
let bres = String::from_utf8(bytes).unwrap();
let res: T = serde_json::from_str(&bres).expect("Could not deserialize input");
Ok(res)
}
#[engine_only_fn]
async fn get_build_state(
_info: StateGeneratorInfo<()>,
) -> Result<IndexPageState, BlamedError<httpreq::MyError>> {
use crate::httpreq;
let body = perseus::utils::cache_fallible_res(
"index",
|| async {
let path = "/views/news/3";
// let res = httpreq::request_client::<Vec<ContentViews>>(path.to_string()).await?;
let res = future::timeout(
Duration::from_secs(5),
httpreq::request_client::<Vec<ContentViews>>(path.to_string()),
)
.await?;
Ok::<Vec<ContentViews>, httpreq::MyError>(res.expect("REASON"))
},
true,
)
.await?;
Ok(IndexPageState { contents: body })
}
Interestingly, when I call the request_client function directly in main(), it works as expected:
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let path = "/views/news/3";
let cnt = client_request::<Vec<ContentViews>>(path.to_string()).await?;
println!("{:#?}", cnt);
Ok(())
}
I have also attached my docker-compose file containing the socket shared socket volume used by the server and front end.
version: "3"
services:
front:
build:
context: .
user: "1000:1000"
volumes:
- mysocket:/tmp:rw
- ./static/:/app/static/
ports:
- 4401:4401
expose:
- "4401"
networks:
default:
name: mynet
external: true
volumes:
mysocket:
external: true
I’m unsure why the frontend container is unable to fetch data from the shared volume. Any insights or suggestions to debug this issue would be greatly appreciated.