Docker 설정 파일 구조 개선 및 .vite 폴더 추적 제거

- .dockerignore 및 docker-compose.yml을 docker/ 디렉토리로 이동
- Makefile의 docker-compose 명령어 경로 업데이트
- .vite/ 폴더를 git 추적에서 제거

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Jay Sheen
2025-09-08 14:06:22 +09:00
parent de253c5d68
commit 8ae42bce07
106 changed files with 526 additions and 131298 deletions

14
docker/.dockerignore Normal file
View File

@@ -0,0 +1,14 @@
node_modules
npm-debug.log
dist
.git
.gitignore
README.md
.env
.env.local
.env.development
.env.production
.DS_Store
coverage
.nyc_output
*.log

50
docker/.htaccess Normal file
View File

@@ -0,0 +1,50 @@
# Enable rewrite engine
RewriteEngine On
# Redirect all traffic to HTTPS in production (uncomment if needed)
# RewriteCond %{HTTPS} off
# RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# React Router - Redirect all requests to index.html
# Don't rewrite files or directories
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule . /index.html [L]
# Prevent direct access to .env files
<Files .env*>
Require all denied
</Files>
# Security headers (if mod_headers is enabled)
<IfModule mod_headers.c>
# Cache static assets for 1 year
<FilesMatch "\.(ico|pdf|flv|jpg|jpeg|png|gif|js|css|swf|svg|woff|woff2|ttf|otf)$">
Header set Cache-Control "max-age=31536000, public, immutable"
</FilesMatch>
# Cache HTML files for 10 minutes
<FilesMatch "\.(html|htm)$">
Header set Cache-Control "max-age=600, must-revalidate"
</FilesMatch>
</IfModule>
# Compression (if mod_deflate is enabled)
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE application/json
AddOutputFilterByType DEFLATE image/svg+xml
</IfModule>
# Error pages (customize as needed)
# ErrorDocument 404 /index.html
# ErrorDocument 500 /index.html

53
docker/Dockerfile Normal file
View File

@@ -0,0 +1,53 @@
# Multi-stage build for React Vite application
# Multi-platform support for AMD64 and ARM64
FROM --platform=$BUILDPLATFORM node:20-alpine3.18 AS builder
# Install git (required for pnpm)
RUN apk add --no-cache git
# Set working directory
WORKDIR /app
# Install pnpm directly without corepack
RUN npm install -g pnpm@latest
# Copy package files
COPY package.json pnpm-lock.yaml ./
# Install dependencies using pnpm
RUN pnpm install --frozen-lockfile
# Copy source code
COPY . .
# Build the application
RUN pnpm run build
# Production stage with Apache
FROM httpd:2.4-alpine AS production
# Install necessary packages
RUN apk add --no-cache bash
# Copy built application from builder stage
COPY --from=builder /app/dist /usr/local/apache2/htdocs/
# Copy Apache configuration
COPY docker/apache.conf /usr/local/apache2/conf/httpd.conf
# Copy .htaccess file for URL rewriting
COPY docker/.htaccess /usr/local/apache2/htdocs/.htaccess
# Copy entrypoint script
COPY docker/entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh
# Expose port 80
EXPOSE 80
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost/ || exit 1
# Start Apache using entrypoint script
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]

35
docker/Dockerfile.dev Normal file
View File

@@ -0,0 +1,35 @@
# Development Dockerfile for hot reloading
# Multi-platform support for AMD64 and ARM64
FROM --platform=$TARGETPLATFORM node:18-alpine
# Set working directory
WORKDIR /app
RUN corepack enable
# Copy package files
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./
RUN \
if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
elif [ -f package-lock.json ]; then npm ci; \
elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm i --frozen-lockfile; \
else echo "Lockfile not found." && exit 1; \
fi
# Install all dependencies (including dev dependencies)
RUN \
if [ -f yarn.lock ]; then yarn run build; \
elif [ -f package-lock.json ]; then npm run build; \
elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm run build; \
else echo "Lockfile not found." && exit 1; \
fi
# Copy source code
COPY . .
# Expose development port
EXPOSE 5173
# Start development server
CMD ["pnpm", "run", "dev"]

145
docker/apache.conf Normal file
View File

@@ -0,0 +1,145 @@
# Apache httpd v2.4 minimal configuration
ServerRoot "/usr/local/apache2"
# Server-wide configuration
ServerAdmin admin@localhost
ServerName localhost
# Listen on port 80
Listen 80
# Load necessary modules
LoadModule mpm_event_module modules/mod_mpm_event.so
LoadModule authn_core_module modules/mod_authn_core.so
LoadModule authz_core_module modules/mod_authz_core.so
LoadModule authz_host_module modules/mod_authz_host.so
LoadModule mime_module modules/mod_mime.so
LoadModule log_config_module modules/mod_log_config.so
LoadModule env_module modules/mod_env.so
LoadModule headers_module modules/mod_headers.so
LoadModule setenvif_module modules/mod_setenvif.so
LoadModule version_module modules/mod_version.so
LoadModule unixd_module modules/mod_unixd.so
LoadModule status_module modules/mod_status.so
LoadModule autoindex_module modules/mod_autoindex.so
LoadModule dir_module modules/mod_dir.so
LoadModule alias_module modules/mod_alias.so
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule deflate_module modules/mod_deflate.so
LoadModule filter_module modules/mod_filter.so
# User and group
<IfModule unixd_module>
User daemon
Group daemon
</IfModule>
# Document root
DocumentRoot "/usr/local/apache2/htdocs"
<Directory "/usr/local/apache2/htdocs">
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
# Enable URL rewriting for React Router
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule . /index.html [L]
</Directory>
# Directory indexes
<IfModule dir_module>
DirectoryIndex index.html index.htm
</IfModule>
# Prevent .htaccess and .htpasswd files from being viewed
<Files ".ht*">
Require all denied
</Files>
# Error log
ErrorLog /proc/self/fd/2
LogLevel warn
# Access log
<IfModule log_config_module>
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %b" common
CustomLog /proc/self/fd/1 common
</IfModule>
# MIME types
<IfModule mime_module>
TypesConfig conf/mime.types
AddType application/javascript .js .mjs
AddType application/json .json
AddType text/css .css
AddType text/html .html .htm
AddType image/svg+xml .svg
AddType image/x-icon .ico
AddType font/woff .woff
AddType font/woff2 .woff2
AddType font/ttf .ttf
AddType font/otf .otf
AddEncoding gzip svgz
</IfModule>
# Enable compression for text-based files
<IfModule deflate_module>
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css
AddOutputFilterByType DEFLATE application/javascript application/json
AddOutputFilterByType DEFLATE application/xml application/xhtml+xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE image/svg+xml
AddOutputFilterByType DEFLATE font/ttf font/otf font/woff font/woff2
# Don't compress already compressed formats
SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|zip|gz|tgz|bz2|rar|7z)$ no-gzip dont-vary
# Make sure proxies don't deliver the wrong content
Header append Vary Accept-Encoding env=!dont-vary
</IfModule>
# Security headers
<IfModule headers_module>
# Prevent clickjacking
Header always set X-Frame-Options "SAMEORIGIN"
# Prevent XSS attacks
Header always set X-XSS-Protection "1; mode=block"
# Prevent MIME sniffing
Header always set X-Content-Type-Options "nosniff"
# Referrer policy
Header always set Referrer-Policy "no-referrer-when-downgrade"
# Content Security Policy
Header always set Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'"
# Remove server signature
Header always unset Server
Header always unset X-Powered-By
</IfModule>
# Cache control for static assets
<FilesMatch "\.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|otf)$">
Header set Cache-Control "max-age=31536000, public, immutable"
</FilesMatch>
# Disable server signature
ServerTokens Prod
ServerSignature Off
# Health check endpoint
<Location "/health">
SetHandler server-status
Require all granted
</Location>
# Include additional configuration files
# Removed IncludeOptional to prevent recursive inclusion
# IncludeOptional conf/*.conf

56
docker/docker-compose.yml Normal file
View File

@@ -0,0 +1,56 @@
version: '3.8'
services:
web:
build:
context: .
dockerfile: docker/Dockerfile
platforms:
- "linux/amd64"
- "linux/arm64"
platform: linux/amd64
image: nice-app-web:latest
container_name: nice-app-web
ports:
- "3000:80"
environment:
- NODE_ENV=production
restart: unless-stopped
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
labels:
- "traefik.enable=true"
- "traefik.http.routers.web.rule=Host(`localhost`)"
- "traefik.http.services.web.loadbalancer.server.port=80"
# Development service (optional)
web-dev:
build:
context: .
dockerfile: docker/Dockerfile.dev
platforms:
- "linux/amd64"
- "linux/arm64"
platform: linux/amd64
container_name: nice-app-web-dev
ports:
- "5173:5173"
volumes:
- .:/app
- /app/node_modules
environment:
- NODE_ENV=development
command: npm run dev
profiles:
- dev
networks:
default:
driver: bridge
volumes:
node_modules:

14
docker/entrypoint.sh Normal file
View File

@@ -0,0 +1,14 @@
#!/bin/bash
set -e
# Replace environment variables in JavaScript files if needed
# This is useful for runtime configuration in Docker containers
# Example: Replace API_URL placeholder with actual environment variable
# if [ ! -z "$API_URL" ]; then
# find /usr/local/apache2/htdocs -name '*.js' -exec sed -i "s|VITE_API_URL_PLACEHOLDER|$API_URL|g" {} +
# fi
# Start Apache in foreground
echo "Starting Apache HTTP Server..."
exec httpd-foreground