I am trying to run a React project using Vite inside a Docker container with Code-Server. The app is proxied through Code-Server at http://localhost:8080/proxy/5173/, but I'm facing issues loading the app in the browser.
Here is my Dockerfile:
FROM node:latest
ENV DEBIAN_FRONTEND=noninteractive
RUN apt update
RUN apt install -y curl
WORKDIR /workspace
RUN curl -fsSL https://code-server.dev/install.sh | sh
COPY ./init.sh .
CMD ["bash", "init.sh"]
The init.sh script initializes the project:
#!/bin/bash
# Check if FRAMEWORK is set
if [ -z "$FRAMEWORK" ]; then
echo "FRAMEWORK is not set"
exit 1
fi
# Check if PROJECT is set
if [ -z "$PROJECT" ]; then
echo "PROJECT is not set"
exit 1
fi
# Create project based on FRAMEWORK
if [ "$FRAMEWORK" = "react" ]; then
npm create vite@latest "$PROJECT" -- --template react --yes
elif [ "$FRAMEWORK" = "vue" ]; then
npm create vite@latest "$PROJECT" -- --template vue --yes
else
echo "Unknown framework: $FRAMEWORK"
exit 1
fi
# Install dependencies
cd "$PROJECT" && npm install
# Start Code-Server
code-server --host 0.0.0.0
I run the container with the following command:
docker run -p 8080:8080 -e FRAMEWORK="react" -e PROJECT="my-app" -e PASSWORD="codepwd" vite-node-portos
Vite Configuration
Initially, I used this vite.config.js:
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [react()],
})
To address the error connect ECONNREFUSED 0.0.0.0:5172
, I modified the config to explicitly bind to 0.0.0.0
:
error image
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [react()],
server: {
host: '0.0.0.0',
port: 5173,
},
})
However, this caused errors in the browser console:
Loading failed for the module with source “http://localhost:8080/proxy/5173/src/main.jsx”.
Loading failed for the module with source “http://localhost:8080/proxy/5173/@react-refresh”.
Loading failed for the module with source “http://localhost:8080/proxy/5173/@vite/client”.
I then updated the vite.config.js to include a base configuration:
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [react()],
server: {
host: '0.0.0.0',
port: 5173,
},
base: '/proxy/5173/',
})
However, this caused the same errors in the browser console:
Loading failed for the module with source “http://localhost:8080/proxy/5173/src/main.jsx”.
Loading failed for the module with source “http://localhost:8080/proxy/5173/@react-refresh”.
Loading failed for the module with source “http://localhost:8080/proxy/5173/@vite/client”.
How can I resolve the module loading errors and correctly serve my Vite app through the Code-Server proxy?
In tools like Project IDX or GitHub Codespaces, Vite projects work without requiring edits to the vite.config.js file to handle proxy paths. Is there a similar way to resolve the proxy issue with Code-Server, so I don't need to modify the Vite config directly?
I fixed this issues with Vite when running a React app in a Docker container using Code-Server and resolved them by setting up a reverse proxy inside the container and using npm run dev -- --host 0.0.0.0
. Here's how I fixed the problem.
FROM node:18
# Install necessary packages
RUN apt-get update && apt-get install -y \
curl \
git \
nginx \
nano \
supervisor \
&& rm -rf /var/lib/apt/lists/*
# Install openvscode-server
ENV VSCODE_VERSION=1.84.2
ENV ARCH=x64
RUN curl -L "https://github.com/gitpod-io/openvscode-server/releases/download/openvscode-server-v${VSCODE_VERSION}/openvscode-server-v${VSCODE_VERSION}-linux-${ARCH}.tar.gz" | tar -xz -C /opt/
RUN ln -s /opt/openvscode-server-v${VSCODE_VERSION}-linux-${ARCH} /opt/openvscode-server
# Set working directory
WORKDIR /workspace
# Copy configuration files
COPY ./supervisord.conf /etc/supervisor/conf.d/supervisord.conf
COPY ./init.sh .
COPY ./generate-nginx-conf.sh /generate-nginx-conf.sh
RUN chmod +x /generate-nginx-conf.sh
RUN chmod +x init.sh
# Expose only the main port
EXPOSE 80
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]
This script initializes the React project and starts the Vite development server.
#!/bin/bash
# Check if FRAMEWORK is set
if [ -z "$FRAMEWORK" ]; then
echo "FRAMEWORK is not set"
exit 1
fi
# Check if PROJECT is set
if [ -z "$PROJECT" ]; then
echo "PROJECT is not set"
exit 1
fi
# Create project based on FRAMEWORK
if [ "$FRAMEWORK" = "react" ]; then
npm create vite@latest "$PROJECT" -- --template react --yes
elif [ "$FRAMEWORK" = "vue" ]; then
npm create vite@latest "$PROJECT" -- --template vue --yes
else
echo "Unknown framework: $FRAMEWORK"
exit 1
fi
cd $PROJECT
npm install
npm run dev -- --host 0.0.0.0
This script generates the nginx
configuration dynamically for both the Vite app and Code-Server.
#!/bin/bash
# Set default values if not provided
VSCODE_DOMAIN=${VSCODE_DOMAIN:-"reactapp.localhost"}
APP_DOMAIN=${APP_DOMAIN:-"reactapp-port-5173.localhost"}
APP_PROXY_PASS=${APP_PROXY_PASS:-"http://localhost:5173"}
# Generate nginx configuration
cat > /etc/nginx/nginx.conf << EOL
user www-data;
worker_processes auto;
pid /run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
map \$http_upgrade \$connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
server_name ${VSCODE_DOMAIN};
access_log /var/log/nginx/vscode.access.log;
location / {
proxy_pass http://127.0.0.1:3001;
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection \$connection_upgrade;
proxy_buffering off;
proxy_http_version 1.1;
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
}
}
server {
listen 80;
server_name ${APP_DOMAIN};
location / {
proxy_pass ${APP_PROXY_PASS};
proxy_http_version 1.1;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host \$host;
proxy_cache_bypass \$http_upgrade;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
}
}
}
EOL
# Test nginx configuration
nginx -t
This supervisord configuration ensures both Nginx and Code-Server run inside the container.
[supervisord]
nodaemon=true
[program:nginx]
command=/usr/sbin/nginx -g 'daemon off;'
autostart=true
autorestart=true
[program:code-server]
command=/opt/openvscode-server/bin/openvscode-server --host 0.0.0.0
autostart=true
autorestart=true
To run the container:
docker build -t react-app-container .
docker run -p 80:80 \
-e FRAMEWORK="react" \
-e PROJECT="my-app" \
-e VSCODE_DOMAIN="reactapp.localhost" \
-e APP_DOMAIN="reactapp-port-5173.localhost" \
react-app-container