9 months ago
I have two projects. In the first project I have 2 services: a backend service (FastAPI) and Frontend service (NextJS), the frontend service is exposed and is talking to the backend using the private network. and everything is working fine.I created another project and I added the backend service only (using the exact github repo - everything same as the first project), but the only difference is that i want to expose this backend using a public url and be able to make a request from my personal computer. When I deploy it there is no error and the logs show the service is up and running:`Uvicorn running on http://[::]:8000 (Press CTRL+C to quit)`I have also added this env variable: PORT:8000 in the Railway service configuration. Here is my docker file:
CMD ["uvicorn", "main:app", "--host", "::", "--port", "8000"]
here is my docker-compose file:
fastapi-app:
container_name: fastapi-app
build: .
ports:
- "8000:8000"
volumes:
- ./app:/home/app
environment:
ENV_NAME: ${ENV_NAME}
networks:
- mainnetwork
command: ["uvicorn", "main:app", "--host", "::", "--port", "8000", "--reload"]
and when I click generate public url, a url is generated, but when I click on it, it shows: Application failed to respond
This error appears to be caused by the application.and I get 502 status code error. So everything is working, except I am not able to reach to the backend using the public url. How to be able to access this backend using the public url?Many thanks in advance.
14 Replies
9 months ago
long story short, the backend service is running, if i deploy a frontend service then it can talk to the backend using the private network and the response coming as expected, so backend is responding through the private network, but when i click on generate public url and i try to expose it, i get 502 error application is not responding.
9 months ago
Use this as your CMD line -
CMD uvicorn main:app --host 0.0.0.0 --port $PORT
This enables public access but removes access from the private network, I would recommend you use hypercorn so that you can dual stack bind to IPv4 for the public network, and IPv6 for the private network.
9 months ago
0.0.0.0
as suggested by Brody should work. Turns out ::
on uvicorn doesn't listen on IPv4 by default [0] and we translate addresses from v6->v4 over our internal routing, so traffic arriving from our proxy will hit your app as IPv4.
[0] https://github.com/encode/uvicorn/discussions/1529
9 months ago
@brody @rc Thank you so much for your help. I updated my dockerfile to be:
CMD ["hypercorn", "main:app", "--bind", "::1:8000", "--bind", "0.0.0.0:8000"]
when i deploy it I can see these logs:
[2024-07-25 02:53:16 +0000] [9] [INFO] Running on http://[::1]:8000 (CTRL + C to quit)
[2024-07-25.02:53:16] [INFO] [info] Running on http://[::1]:8000 (CTRL + C to quit)
[2024-07-25 02:53:16 +0000] [9] [INFO] Running on http://0.0.0.0:8000 (CTRL + C to quit)
[2024-07-25.02:53:16] [INFO] [info] Running on http://0.0.0.0:8000 (CTRL + C to quit)
I have also ran it locally and tested it using curl for both ipv4 and ipv6 and it worked for both. But when deploying it to railway, still the same issues, I still get: "Application failed to respond" with status code 502.
9 months ago
ahhh, hate when this happened, turned out im on the prod env and did not copy the port env var, so now it is working, silly error :D.
Thank you so much for the help!!
9 months ago
PORT
will be randomly generated at runtime, if you wish to use this service with the private network use the same CMD line and simply set a fixed PORT
service variable.
9 months ago
Oh wow, since you already mentioned that, my frontend was able to talk to my backend and call the apis, but now Im getting this:
Mixed Content: The page at 'https://dev.example.com/signup' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://example.railway.internal:8000/signup'. This request has been blocked; the content must be served over HTTPS.
9 months ago
A client side rendered frontend app needs to call the public domain of the backend, it wouldn't be a very private network if anyone's browser could call your private domain.
9 months ago
Yeah, make sense. Im using NextJS app. Im not a frontend guy so not really sure if the backend endpoint should be public or not. However, I was thinking to keep the frontend talking to the backend using the private network, while i use the backend exposed url for other purposes (such as login using Google callback for authentication).
9 months ago
The frontend would need to be server side rendered to talk to the backend via the private network.
4 months ago
Hi, I'm getting the same issue with fastapi app. (https://limitbreak-production.up.railway.app/)
I tried using hypercorn, setting port env to 8000/5000, also I tried with hard coded values in docker file.
If I run docker locally is working well, the problem is when I deploy to railway, it finish successfully but when I request from Postman to the api I got a 502 status response.
I don't know what else I should try.
those are logs from Deploy Logs tab:
You reached the start of the range → Dec 27, 2024 7:09 PM
Starting Container
this is my dockerfile:
# Use Python base image
FROM python:3.12-slim
# Set environment variables
# Prevent Python from writing .pyc files
ENV PYTHONDONTWRITEBYTECODE=1
# Prevent buffering of stdout and stderr
ENV PYTHONUNBUFFERED=1
ENV PYTHONPATH=/app
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE ${PORT}
CMD ["sh", "-c", "hypercorn main:app --bind ::1:${PORT} --bind 0.0.0.0:${PORT}"]
4 months ago
chinocejas, please see our docs on this topic -
https://docs.railway.com/guides/private-networking#python--hypercorn
tl;dr - you need to use ::
not ::1
brody
chinocejas, please see our docs on this topic -https://docs.railway.com/guides/private-networking#python--hypercorntl;dr - you need to use :: not ::1
4 months ago
thanks for answer brody.
I tied with those options and I still getting same issue (502 Status response)
CMD ["sh", "-c", "hypercorn main:app --bind [::]:${PORT-8000}"]
CMD ["sh", "-c", "hypercorn main:app --bind [::]:${PORT-8000} --bind 0.0.0.0:${PORT-8000}"]