I’m trying to connect a websocket from my Python backend to Django. In my development environment, it works fine with ws, but when deployed in my AWS container, I must use wss because of my SSL certificate.
Below is my docker-compose file. The lines commented out are things I’ve tried (I’ve replaced sensitive data with xxxxxx
).
version: '3.8'
services:
traefik:
image: "traefik:v2.9"
container_name: "traefik2"
ports:
- target: 80
published: 80
mode: host
- target: 443
published: 443
mode: host
- target: 8080
published: 8080
mode: host
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- ../TRAEFIK/letsencrypt:/letsencrypt
networks:
- default
command:
- "--accesslog=true"
- "--providers.docker.endpoint=unix:///var/run/docker.sock"
- "--api=true"
- "--api.insecure=true"
- "--api.dashboard=true"
- "--providers.docker.swarmMode=false"
- "--providers.docker.exposedbydefault=false"
- "--providers.docker.network=ukcl-net"
- "--entrypoints.web.address=:80"
- "--entrypoints.web.http.redirections.entryPoint.to=websecure"
- "--entrypoints.web.http.redirections.entryPoint.scheme=https"
- "--entrypoints.web.http.redirections.entrypoint.permanent=true"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.myhttpchallenge.acme.httpchallenge=true"
- "--certificatesresolvers.myhttpchallenge.acme.httpchallenge.entrypoint=web"
- "--certificatesresolvers.myhttpchallenge.acme.email=xxxxxxxxxxxxxxxx"
- "--certificatesresolvers.myhttpchallenge.acme.storage=/letsencrypt/acme.json"
- "--certificatesresolvers.myhttpchallenge2.acme.httpchallenge=true"
- "--certificatesresolvers.myhttpchallenge2.acme.httpchallenge.entrypoint=web"
- "--certificatesresolvers.myhttpchallenge2.acme.email=xxxxxxxxxxxxxxx"
- "--certificatesresolvers.myhttpchallenge2.acme.storage=/letsencrypt/acme2.json"
# - "traefik.http.routers.wss.rule=Host(`ws.${HOST}`)"
# - "traefik.tcp.services.wss.loadbalancer.server.port=80"
# - "traefik.http.routers.wss.entrypoints=websecure"
deploy:
labels:
- traefik.enable=true
- traefik.docker.network=ukcl-net
- traefik.http.routers.stack-traefik.rule=Host(`xxxxx`)
- traefik.http.routers.traefik.entrypoints=web
- traefik.http.routers.traefik.service=api@internal
- traefik.http.services.traefik.loadbalancer.server.port=80
logging:
driver: "json-file"
options:
max-size: "5m"
max-file: "5"
# ws-service:
# deploy:
# labels:
# - traefik.http.routers.ws-service-wss.rule=Host(`xxxxxxx`)
# - traefik.http.routers.ws-service-wss.entrypoints=wss
# - traefik.http.routers.ws-service-wss.tls=true
# - traefik.http.routers.ws-service-wss.tls.certresolver=dns
frontend:
build: ./front_end/frontend
image: frontend
container_name: frontend
hostname: frontend
depends_on:
- traefik
networks:
- default
labels:
- traefik.enable=true
- traefik.docker.network=ukcl-net
- traefik.http.routers.frontend.rule=Host(`xxxxxx`)
- traefik.http.routers.frontend.entrypoints=websecure
- traefik.http.routers.frontend.tls.certresolver=myhttpchallenge
- traefik.http.services.frontend.loadbalancer.server.port=80
ports:
- 8001:8001
volumes:
- /home/ec2-user/big_ui_system/front_end/frontend/.env:/frontend/.env
backend:
build:
context: .
dockerfile: Dockerfile_backend
image: backend
container_name: backend
depends_on:
- rabbitmq
networks:
- default
labels:
- traefik.enable=true
- traefik.docker.network=ukcl-net
- traefik.http.routers.backend.rule=Host(`xxxxxxxx`)
- traefik.http.routers.backend.tls.certresolver=myhttpchallenge2
- traefik.http.services.backend.loadbalancer.server.port=8000
ports:
- 8000:8000
networks:
default:
name: ${NETWORK:-ukcl-net}
external: true
What should I do to make this work? There aren't any good tutorials I can find.
(Extra information in case it helps)
docker-compose up
works just fine, but then my backend throws an error when it tries to connect to just.
I’ve made a minimal reproducible example here:
https://github.com/tgmlearn/min_reprocable_wss_with_traefik_and_docker
I’ve replaced any sensitive information, such as IP addresses or domain names, with xxxxxxxxxx
.
update (more info)
below we have
the logs for the frontend and traefik being printed
the error when the backend starts up and tries to send a wss message to the frontend
the logs for the frontend and the backend again (for comparison)
-1)
[ec2-user@ip-172-31-89-174 new_the_guys]$ docker-compose up backenddocker logs frontend
Watching for file changes with StatReloader HTTP GET / 200 [0.01, 172.18.0.2:43866]
[ec2-user@ip-172-31-89-174 new_the_guys]$ docker logs traefik2 time="2023-06-28T10:55:30Z" level=info msg="Configuration loaded from flags." 157.231.75.146 - - [28/Jun/2023:10:55:39 +0000] "GET / HTTP/2.0" 200 1317 "-" "-" 1 "frontend@docker" "http://172.18.0.4:80" 11ms
2
[ec2-user@ip-172-31-89-174 new_the_guys]$ docker-compose up backend [+] Running 1/0 ✔ Container backend Created 0.0s Attaching to backend backend | starty mc start start backend | wss://frontend:80/ws/endpoint/chat/ ==== url were using backend | Traceback (most recent call last): backend | File "/usr/local/lib/python3.9/site-packages/websockets/legacy/client.py", line 655, in await_impl_timeout backend | return await self.await_impl() backend | File "/usr/local/lib/python3.9/site-packages/websockets/legacy/client.py", line 659, in await_impl backend | _transport, _protocol = await self._create_connection() backend | File "/usr/local/lib/python3.9/asyncio/base_events.py", line 1090, in create_connection backend | transport, protocol = await self._create_connection_transport( backend | File "/usr/local/lib/python3.9/asyncio/base_events.py", line 1120, in _create_connection_transport backend | await waiter backend | asyncio.exceptions.CancelledError backend | backend | During handling of the above exception, another exception occurred: backend | backend | Traceback (most recent call last): backend | File "/backend/./main.py", line 61, in <module> backend | send_SMS_caller() backend | File "/backend/./main.py", line 57, in send_SMS_caller backend | asyncio.run(SendSMS()) backend | File "/usr/local/lib/python3.9/asyncio/runners.py", line 44, in run backend | return loop.run_until_complete(main) backend | File "/usr/local/lib/python3.9/asyncio/base_events.py", line 647, in run_until_complete backend | return future.result() backend | File "/backend/./main.py", line 36, in SendSMS backend | async with websockets.connect(ws_url, ping_interval=None) as websocket: backend | File "/usr/local/lib/python3.9/site-packages/websockets/legacy/client.py", line 637, in aenter backend | return await self backend | File "/usr/local/lib/python3.9/site-packages/websockets/legacy/client.py", line 655, in await_impl_timeout backend | return await self.await_impl() backend | File "/usr/local/lib/python3.9/site-packages/websockets/legacy/async_timeout.py", line 169, in aexit backend | self._do_exit(exc_type) backend | File "/usr/local/lib/python3.9/site-packages/websockets/legacy/async_timeout.py", line 252, in _do_exit backend | raise asyncio.TimeoutError backend | asyncio.exceptions.TimeoutError backend | backend exited with code 1
3
[ec2-user@ip-172-31-89-174 new_the_guys]$ docker logs frontend Watching for file changes with StatReloader HTTP GET / 200 [0.01, 172.18.0.2:43866]
[ec2-user@ip-172-31-89-174 new_the_guys]$ docker logs traefik2 time="2023-06-28T10:55:30Z" level=info msg="Configuration loaded from flags." 157.231.75.146 - - [28/Jun/2023:10:55:39 +0000] "GET / HTTP/2.0" 200 1317 "-" "-" 1 "frontend@docker" "http://172.18.0.4:80" 11ms
theres no difference between the logs before and after and the error from the backend basically just says it cant connect, and the error from the backend is a basic websocket cant connect error
also heres my security groups