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
