Basically, I'm running a webapp with this stack: Backend: FastAPI (python) which depends on database Database: MySQL (being connected with via python-connector) Frontend: React Functional (rn it's dependency is set to backend, but technically no dependencies)
The backend is connecting to the database via localhost, and is being served on the public ip
I can access it at just fine at mydomain.com:8000/api
However when I'm trying to access mydomain.com
, docker is setup to forward port 3000 to port 80, however it can't request react and, I get the ERR_CONNECTION_REFUSED
error
In alot of similar issues people forget to forward port 3000 to 80 however i'm doing this...
Also, when I install npm & the react project on my Ubuntu Server, the frontend is accessible via mydomain.com:3000
In the docker-compose.yml when I change the ports from "REACT_PORT : 80 " To "3000 : 3000 " And that's accessible via our public ip.
Should I just port forward 3000 to 80 on the main linux server? how to do?
Docker Files
Frontend docker file
# pull official base image for node
FROM node:16-buster-slim
# set working directory
WORKDIR /app
# add `/app/node_modules/.bin` to PATH
ENV PATH /app/node_modules/.bin:$PATH
# install dependencies
COPY package.json ./
COPY package-lock.json ./
RUN npm i -g npm@latest
RUN npm install
# copy all src files to the container
COPY . .
# Expose port
EXPOSE 3000
EXPOSE 80
# start the web app
CMD ["npm", "run", "start"]
docker-compose.yml
version: "3.9"
services:
db:
image: mysql:${MYSQL_VERSION}
restart: always
environment:
- MYSQL_DATABASE=${MYSQL_DB}
- MYSQL_USER=${MYSQL_USERNAME}
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
ports:
- "${MYSQL_PORT}:${MYSQL_PORT}"
expose:
- "${MYSQL_PORT}"
volumes:
- db:/var/lib/mysql
networks:
- mysql_network
backend:
container_name: fastapi-backend
build: ./backend/app
volumes:
- ./backend:/code
ports:
- "${FASTAPI_PORT}:${FASTAPI_PORT}"
env_file:
- .env
depends_on:
- db
networks:
- mysql_network
- backend
restart: always
frontend:
container_name: react-frontend
build: ./frontend/client
ports:
#This doesn't work for some reason?
- "${REACT_PORT}:80"
#When I do this, I can access react via public ip just fine..:
- "3000:3000"
depends_on:
- backend
networks:
- backend
restart: always
volumes:
db:
driver: local
networks:
backend:
driver: bridge
mysql_network:
driver: bridge
React/NPM Files
package.json
{
"name": "client",
"version": "0.1.0",
"private": true,
"dependencies": {
"@reduxjs/toolkit": "^1.8.2",
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.1.1",
"@testing-library/user-event": "^13.5.0",
"bootstrap": "^5.1.3",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"react-redux": "^8.0.2",
"react-router-dom": "^6.3.0",
"react-scripts": "5.0.1",
"universal-cookie": "^4.0.4",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
Ubuntu UFW status
root@localhost:~/director# ufw status verbose
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), deny (routed)
New profiles: skip
To Action From
-- ------ ----
3306/tcp ALLOW IN Anywhere
22/tcp ALLOW IN Anywhere
80/tcp ALLOW IN Anywhere
443 ALLOW IN Anywhere
3000 ALLOW IN Anywhere
3306/tcp (v6) ALLOW IN Anywhere (v6)
22/tcp (v6) ALLOW IN Anywhere (v6)
80/tcp (v6) ALLOW IN Anywhere (v6)
443 (v6) ALLOW IN Anywhere (v6)
3000 (v6) ALLOW IN Anywhere (v6)
doing curl -l mydomain.com:8000
curl -l domain.com:8000
{"detail":"Not authenticated"}
Our backend is working and public
docker inspect react_frontend
[
{
"Id": "533f96d538bcf28827d5ad5ead69dc97b97c79bfef1d1e31e3847f15ceb0621f",
"Created": "2022-06-27T04:00:18.459838372Z",
"Path": "docker-entrypoint.sh",
"Args": [
"npm",
"start"
],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 57578,
"ExitCode": 0,
"Error": "",
"StartedAt": "2022-06-27T04:00:20.253120387Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:698f3ce60c6ba12f39dcf371bd4be556c1cb4aac9c7f95fd4589c079ec4e337b",
"ResolvConfPath": "/var/lib/docker/containers/533f96d538bcf28827d5ad5ead69dc97b97c79bfef1d1e31e3847f15ceb0621f/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/533f96d538bcf28827d5ad5ead69dc97b97c79bfef1d1e31e3847f15ceb0621f/hostname",
"HostsPath": "/var/lib/docker/containers/533f96d538bcf28827d5ad5ead69dc97b97c79bfef1d1e31e3847f15ceb0621f/hosts",
"LogPath": "/var/lib/docker/containers/533f96d538bcf28827d5ad5ead69dc97b97c79bfef1d1e31e3847f15ceb0621f/533f96d538bcf28827d5ad5ead69dc97b97c79bfef1d1e31e3847f15ceb0621f-json.log",
"Name": "/react-frontend",
"RestartCount": 0,
"Driver": "overlay2",
"Platform": "linux",
"MountLabel": "",
"ProcessLabel": "",
"AppArmorProfile": "docker-default",
"ExecIDs": null,
"HostConfig": {
"Binds": [],
"ContainerIDFile": "",
"LogConfig": {
"Type": "json-file",
"Config": {}
},
"NetworkMode": "scheduleplatform_backend",
"PortBindings": {
"80/tcp": [
{
"HostIp": "",
"HostPort": "3000"
}
]
},
"RestartPolicy": {
"Name": "always",
"MaximumRetryCount": 0
},
"AutoRemove": false,
"VolumeDriver": "",
"VolumesFrom": [],
"CapAdd": null,
"CapDrop": null,
"CgroupnsMode": "private",
"Dns": null,
"DnsOptions": null,
"DnsSearch": null,
"ExtraHosts": null,
"GroupAdd": null,
"IpcMode": "private",
"Cgroup": "",
"Links": null,
"OomScoreAdj": 0,
"PidMode": "",
"Privileged": false,
"PublishAllPorts": false,
"ReadonlyRootfs": false,
"SecurityOpt": null,
"UTSMode": "",
"UsernsMode": "",
"ShmSize": 67108864,
"Runtime": "runc",
"ConsoleSize": [
0,
0
],
"Isolation": "",
"CpuShares": 0,
"Memory": 0,
"NanoCpus": 0,
"CgroupParent": "",
"BlkioWeight": 0,
"BlkioWeightDevice": null,
"BlkioDeviceReadBps": null,
"BlkioDeviceWriteBps": null,
"BlkioDeviceReadIOps": null,
"BlkioDeviceWriteIOps": null,
"CpuPeriod": 0,
"CpuQuota": 0,
"CpuRealtimePeriod": 0,
"CpuRealtimeRuntime": 0,
"CpusetCpus": "",
"CpusetMems": "",
"Devices": null,
"DeviceCgroupRules": null,
"DeviceRequests": null,
"KernelMemory": 0,
"KernelMemoryTCP": 0,
"MemoryReservation": 0,
"MemorySwap": 0,
"MemorySwappiness": null,
"OomKillDisable": null,
"PidsLimit": null,
"Ulimits": null,
"CpuCount": 0,
"CpuPercent": 0,
"IOMaximumIOps": 0,
"IOMaximumBandwidth": 0,
"MaskedPaths": [
"/proc/asound",
"/proc/acpi",
"/proc/kcore",
"/proc/keys",
"/proc/latency_stats",
"/proc/timer_list",
"/proc/timer_stats",
"/proc/sched_debug",
"/proc/scsi",
"/sys/firmware"
],
"ReadonlyPaths": [
"/proc/bus",
"/proc/fs",
"/proc/irq",
"/proc/sys",
"/proc/sysrq-trigger"
]
},
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/f9449860ca28f3641e74ef010fa6bb54383a33a975dce28519f5cfe609ff61d2-init/diff:/var/lib/docker/overlay2/7d8ad12b25cf6e4e0093e811370194cc6c1f72aa443d7d8f0ab69e97715f4c82/diff:/var/lib/docker/overlay2/b530ee218be07eb3a58df7a2f134b4e23cd22ad04b35dc7cbb75f3f07a206280/diff:/var/lib/docker/overlay2/94b5584c91af3dda4376092abdb9b7ff80937311741b96deca22e4b3aaf3a7c7/diff:/var/lib/docker/overlay2/4d8194094b484dfd94ca7473e3e13bfa5962879fd81942710f0aa096199a87c3/diff:/var/lib/docker/overlay2/aeb4c3cd54338efa1d44e1fc24c8a8f91bf672e47771fd0e308b3f65ab753f07/diff:/var/lib/docker/overlay2/9ddac11aa66b2d843b2391c3ad0798f8e372adfffeaec87882322de663b398e5/diff:/var/lib/docker/overlay2/e874192d15482d34ed8a80ef205b55005c84fcad0a7726822de258963191ec10/diff:/var/lib/docker/overlay2/8b162bdb3415e166a91518df47e1bed0bfff2d89568a2653f74e66cb3931773a/diff:/var/lib/docker/overlay2/a18946af0ee112612099819a9db0a3cbef5d1e2264904e6a8405868ab111634a/diff:/var/lib/docker/overlay2/b94b4e7d1af7280ad586d6f3366a161ec0d5cf9f858f0f20139b2ab0a72acfb7/diff:/var/lib/docker/overlay2/052c70a96ef76a7c32d609b98ec679ad7c6a74a28623b870bd729447bbc6086c/diff",
"MergedDir": "/var/lib/docker/overlay2/f9449860ca28f3641e74ef010fa6bb54383a33a975dce28519f5cfe609ff61d2/merged",
"UpperDir": "/var/lib/docker/overlay2/f9449860ca28f3641e74ef010fa6bb54383a33a975dce28519f5cfe609ff61d2/diff",
"WorkDir": "/var/lib/docker/overlay2/f9449860ca28f3641e74ef010fa6bb54383a33a975dce28519f5cfe609ff61d2/work"
},
"Name": "overlay2"
},
"Mounts": [],
"Config": {
"Hostname": "533f96d538bc",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"ExposedPorts": {
"3000/tcp": {},
"80/tcp": {}
},
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/app/node_modules/.bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"NODE_VERSION=16.15.1",
"YARN_VERSION=1.22.19"
],
"Cmd": [
"npm",
"start"
],
"Image": "scheduleplatform_frontend",
"Volumes": null,
"WorkingDir": "/app",
"Entrypoint": [
"docker-entrypoint.sh"
],
"OnBuild": null,
"Labels": {
"com.docker.compose.config-hash": "a02c886422905cf77d66a479bb9967d4a85bdd8c3ed0369665dae6afc9b34099",
"com.docker.compose.container-number": "1",
"com.docker.compose.oneoff": "False",
"com.docker.compose.project": "scheduleplatform",
"com.docker.compose.project.config_files": "docker-compose.yml",
"com.docker.compose.project.working_dir": "/root/SchedulePlatform",
"com.docker.compose.service": "frontend",
"com.docker.compose.version": "1.29.2"
}
},
"NetworkSettings": {
"Bridge": "",
"SandboxID": "014cba17fd5ce070c42b6257a05149d7c78b7556d941d5f790c8c0f27e70a8b1",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {
"3000/tcp": null,
"80/tcp": [
{
"HostIp": "0.0.0.0",
"HostPort": "3000"
},
{
"HostIp": "::",
"HostPort": "3000"
}
]
},
"SandboxKey": "/var/run/docker/netns/014cba17fd5c",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "",
"Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "",
"IPPrefixLen": 0,
"IPv6Gateway": "",
"MacAddress": "",
"Networks": {
"scheduleplatform_backend": {
"IPAMConfig": null,
"Links": null,
"Aliases": [
"533f96d538bc",
"frontend"
],
"NetworkID": "9a6ff7cb0c0d725de46e21e309cd0e5708995faffb00f099c8980127f8a9c68c",
"EndpointID": "c6c22efd535ee4beaa732730143268a4d372d2cecb2537f00013a7b057416852",
"Gateway": "172.20.0.1",
"IPAddress": "172.20.0.3",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:14:00:03",
"DriverOpts": null
}
}
}
}
]
CodePudding user response:
I gave up with docker and now use NGINX to point port 80 to 3000...
Basically, in my docker-compose.yml I point the react port to itself like:
frontend:
container_name: react-frontend
build: ./frontend/client
ports:
- "${REACT_PORT}:${REACT_PORT}"
depends_on:
- backend
networks:
- backend
restart: always
And with NGINX, I edit the config file doing:
nano etc/nginx/nginx.conf
then in the http {} section of this config, I removed include /etc/nginx/sites-enabled/*;
and added
server {
listen 80;
location / {proxy_pass http://localhost:3000/; }
}
and then reloaded nginx, now docker is forwarding at port 3000 and nginx is pointing 80 to that port.
This method works, I still don't understand why Docker wasn't able to port forward that, I even checked my netstat and nothing was running on port 80... weird...