I have a React app that connects to a backend. The backend is configured for HTTPS and works just fine, until I try to make any requests to it from the React app. I have configured both to be on different subdomains of one common domain (via hosts file; they're both actually running on localhost, although I tried figuring out how to change that) so CORS works fine, but it refuses to set the PHP session cookie because the frontend is HTTP, while the backend is HTTPS:
Both are running in Docker, separate projects, separate docker-compose files; backend on ports 80/443, frontend on just 3011 (maybe that is the problem, but I can't set frontend to also use ports 80/443 because they're already in use).
I have been trying for way too long to get my Dockerized React app to run in HTTPS mode. According to https://create-react-app.dev/docs/using-https-in-development/ (and a ton of other sources on the web, such as https://www.mariokandut.com/how-to-setup-https-ssl-in-localhost-react/ and https://www.youtube.com/watch?v=neT7fmZ6sDE), it should be as easy as generating a certificate and specifying some environment variables leading to the certificate and its key.
However, when I do that, it still refuses to run in HTTPS mode, and I cannot figure out why that is:
It seems pretty obvious to me that the problem is caused by Docker, but I am not very familiar with it, and I've spent the entire day trying to fix various problems with this whole thing, but this one I just can't handle, so here I am.
docker-compose.dev.yml
:
version: "3.8"
services:
node:
environment:
- WATCHPACK_POLLING=true
build:
context: .
target: dev
volumes:
- ./:/opt/project
- /opt/project/node_modules/
ports:
- "3011:3011"
Relevant part of Dockerfile
:
FROM node:lts-alpine AS dev
WORKDIR /opt/project
COPY . .
RUN npm ci
ENV HTTPS=true
ENV SSL_CRT_FILE=./ssl/cert.pem
ENV SSL_KEY_FILE=./ssl/key.pem
CMD npm run start
What causes this cursed React app to not work in HTTPS mode?
Since your server is running over HTTPS and you're already using the Secure
attribute, you can enable SameSite=None
in your cookie settings to properly support cross-domain credentials.
Then you should be able to connect using any client host (CORS notwithstanding).
This might be convenient if you intend on using separate hosts in production since you wouldn't need to toggle SameSite
based on environment.
Otherwise, it doesn't look like you're running the React app with HTTPS=true
. If you added the ENV
commands to your Dockerfile
after initially running the app, you'll need to rebuild your image
docker compose build
Alternately, avoid things that might change regularly in your Docker build and simply set them at runtime
environment:
- WATCHPACK_POLLING=true
- HTTPS=true
- SSL_CRT_FILE=/opt/project/ssl/cert.pem
- SSL_KEY_FILE=/opt/project/ssl/key.pem
Then you should be able to open https://localhost:3011
in your browser (or whatever mapped hostname you feel like using).
cra-node-1 | Starting the development server...
cra-node-1 |
cra-node-1 | Compiled successfully!
cra-node-1 |
cra-node-1 | You can now view cra in the browser.
cra-node-1 |
cra-node-1 | Local: https://localhost:3011
cra-node-1 | On Your Network: https://172.18.0.2:3011
cra-node-1 |
cra-node-1 | Note that the development build is not optimized.
cra-node-1 | To create a production build, use npm run build.
cra-node-1 |
cra-node-1 | webpack compiled successfully