The Centinela water treatment monitoring system uses a multi-stage Docker build process to create optimized production containers. This guide covers building and running the application with Docker.
Docker Architecture
The Dockerfile uses a two-stage build process:
Build Stage : Compiles the React/Vite application with all environment variables
Runtime Stage : Serves the static files using Nginx Alpine
Prerequisites
Before deploying with Docker, ensure you have:
Docker installed (version 20.10 or higher)
Docker Compose (optional, for orchestrated deployments)
Environment variables prepared (see Environment Variables )
Building the Docker Image
Navigate to project directory
Build with environment arguments
Build the Docker image with required environment variables as build arguments: docker build \
--build-arg VITE_APP_NAME="Centinela" \
--build-arg VITE_ENTORNO="desarrollo" \
--build-arg SECRET="your-secret-key" \
-t centinela:dev .
Environment variables are baked into the build at compile time. You must rebuild the image if you need to change these values.
Verify the build
Check that your image was created successfully: docker images | grep centinela
Running the Container
Once built, run the container with the following command:
docker run -d \
--name centinela-app \
-p 80:80 \
--restart unless-stopped \
centinela:latest
Run container in detached mode (background)
--name
string
default: "centinela-app"
Assign a name to the container for easier management
Map host port 80 to container port 80. Adjust as needed (e.g., 8080:80)
--restart
string
default: "unless-stopped"
Container restart policy. Options: no, on-failure, always, unless-stopped
Docker Build Process Details
Here’s what happens during the multi-stage build:
Build Stage
# ---- Build Stage ----
FROM node:alpine AS build
WORKDIR /app
ARG VITE_APP_NAME
ARG VITE_ENTORNO
ARG SECRET
ENV VITE_APP_NAME=$VITE_APP_NAME
ENV VITE_ENTORNO=$VITE_ENTORNO
ENV SECRET=$SECRET
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
This stage:
Uses Node.js Alpine for a lightweight build environment
Accepts build arguments for environment configuration
Installs dependencies and builds the Vite application
Outputs compiled assets to /app/dist
Runtime Stage
# ---- Runtime Stage ----
FROM nginx:alpine AS runtime
COPY --from=build /app/dist /usr/share/nginx/html
# Opcional: Copia una configuración personalizada de Nginx si es necesario
COPY nginx/default.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD [ "nginx" , "-g" , "daemon off;" ]
This stage:
Uses Nginx Alpine for minimal production footprint
Copies built assets from the build stage
Applies custom Nginx configuration for SPA routing
Exposes port 80 for web traffic
The final image does NOT contain Node.js or source code, only the compiled static assets and Nginx. This significantly reduces image size and attack surface.
Docker Compose Example
For easier deployment management, create a docker-compose.yml file:
version : '3.8'
services :
centinela :
build :
context : .
args :
VITE_APP_NAME : "Centinela"
VITE_ENTORNO : "produccion"
SECRET : "${SECRET}"
container_name : centinela-app
ports :
- "80:80"
restart : unless-stopped
networks :
- centinela-network
networks :
centinela-network :
driver : bridge
Then deploy with:
# Set environment variables
export SECRET = "your-secret-key"
# Start services
docker-compose up -d
# View logs
docker-compose logs -f centinela
# Stop services
docker-compose down
Container Management
Viewing Logs
# Real-time logs
docker logs -f centinela-app
# Last 100 lines
docker logs --tail 100 centinela-app
Stopping and Starting
# Stop container
docker stop centinela-app
# Start container
docker start centinela-app
# Restart container
docker restart centinela-app
Removing Containers
# Remove stopped container
docker rm centinela-app
# Force remove running container
docker rm -f centinela-app
Image Optimization
The multi-stage build provides significant size benefits:
Stage Size Contents Build ~500MB Node.js + dependencies + source code Runtime ~50MB Nginx + compiled assets only
The final production image is approximately 90% smaller than a single-stage build, resulting in faster deployments and reduced storage costs.
Health Checks
Add a health check to your Docker run command:
docker run -d \
--name centinela-app \
-p 80:80 \
--health-cmd= "wget --no-verbose --tries=1 --spider http://localhost/ || exit 1" \
--health-interval=30s \
--health-timeout=10s \
--health-retries=3 \
centinela:latest
Or in docker-compose.yml:
healthcheck :
test : [ "CMD" , "wget" , "--no-verbose" , "--tries=1" , "--spider" , "http://localhost/" ]
interval : 30s
timeout : 10s
retries : 3
start_period : 40s
Troubleshooting
Build Failures
If the build fails, check:
All build arguments are provided
Network connectivity for npm install
Sufficient disk space for build process
# Check Docker disk usage
docker system df
# Clean up unused resources
docker system prune -a
Container Won’t Start
# Check container logs
docker logs centinela-app
# Inspect container configuration
docker inspect centinela-app
# Check if port is already in use
sudo netstat -tulpn | grep :80
Environment Variables Not Applied
Remember that Vite environment variables are embedded at build time, not runtime. You must rebuild the Docker image to change them.
Next Steps
Environment Variables Configure application settings and API endpoints
Nginx Configuration Customize web server settings and routing