Steve/EV Dashboard/nginx 도커파일 및 설정파일 추가
This commit is contained in:
35
ev-charging-backend/.env
Normal file
35
ev-charging-backend/.env
Normal file
@@ -0,0 +1,35 @@
|
||||
# ── 데이터베이스 ──
|
||||
POSTGRES_DB=ev_charging
|
||||
POSTGRES_USER=evuser
|
||||
POSTGRES_PASSWORD=evpass1234
|
||||
POSTGRES_HOST=postgres
|
||||
POSTGRES_PORT=5432
|
||||
|
||||
# ── Redis ──
|
||||
REDIS_HOST=redis
|
||||
REDIS_PORT=6379
|
||||
|
||||
# ── Steve OCPP 서버 ──
|
||||
STEVE_BASE_URL=https://s1.byunc.com/steve
|
||||
STEVE_API_USER=admin
|
||||
STEVE_API_PASSWORD=changeme
|
||||
|
||||
# ── 토스페이먼츠 ──
|
||||
TOSS_CLIENT_KEY=test_ck_Poxy1XQL8RYmzR9JgL5lr7nO5Wml
|
||||
TOSS_SECRET_KEY=test_sk_ZLKGPx4M3M90lvAvzx1n3BaWypv1
|
||||
#TOSS_CLIENT_KEY=test_ck_xxxxxxxxxx
|
||||
#TOSS_SECRET_KEY=test_sk_xxxxxxxxxx
|
||||
|
||||
# ── 요금 설정 (원/kWh) ──
|
||||
ELECTRICITY_RATE=120
|
||||
SERVICE_MARGIN=50
|
||||
|
||||
# ── JWT ──
|
||||
JWT_SECRET=your-super-secret-key-change-this
|
||||
JWT_ALGORITHM=HS256
|
||||
JWT_EXPIRE_MINUTES=1440
|
||||
|
||||
# ── 서버 ──
|
||||
SERVER_HOST=0.0.0.0
|
||||
SERVER_PORT=8000
|
||||
DEBUG=true
|
||||
15
ev-charging-backend/Dockerfile
Normal file
15
ev-charging-backend/Dockerfile
Normal file
@@ -0,0 +1,15 @@
|
||||
FROM python:3.11-slim
|
||||
|
||||
WORKDIR /code
|
||||
|
||||
# 시스템 패키지
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
gcc libpq-dev && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY requirements.txt .
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
COPY ./app /code/app
|
||||
|
||||
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]
|
||||
10
ev-charging-backend/Dockerfile.proxy
Executable file
10
ev-charging-backend/Dockerfile.proxy
Executable file
@@ -0,0 +1,10 @@
|
||||
FROM python:3.11-slim
|
||||
|
||||
WORKDIR /code
|
||||
|
||||
RUN pip install --no-cache-dir websockets aiohttp
|
||||
|
||||
COPY entrypoint-proxy.sh /code/
|
||||
RUN chmod +x /code/entrypoint-proxy.sh
|
||||
|
||||
CMD ["/code/entrypoint-proxy.sh"]
|
||||
84
ev-charging-backend/docker-compose.yml
Normal file
84
ev-charging-backend/docker-compose.yml
Normal file
@@ -0,0 +1,84 @@
|
||||
services:
|
||||
# ── FastAPI 백엔드 ──
|
||||
api:
|
||||
build: .
|
||||
container_name: ev-api
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "8000:8000"
|
||||
env_file:
|
||||
- .env
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
volumes:
|
||||
- ./app:/code/app
|
||||
- ./dashboard.html:/code/dashboard.html:ro
|
||||
- ./simulator.html:/code/simulator.html:ro
|
||||
networks:
|
||||
- ev-net
|
||||
|
||||
# ── OCPP 프록시 서버 ──
|
||||
proxy:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.proxy
|
||||
container_name: ev-proxy
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "9002:9002"
|
||||
- "9003:9003"
|
||||
volumes:
|
||||
- ./ocpp_proxy_server.py:/code/ocpp_proxy_server.py:ro
|
||||
- ./proxy_control.html:/code/proxy_control.html:ro
|
||||
- proxy_logs:/code/ocpp_logs
|
||||
- proxy_config:/code/config
|
||||
networks:
|
||||
- ev-net
|
||||
|
||||
# ── PostgreSQL ──
|
||||
postgres:
|
||||
image: postgres:16-alpine
|
||||
container_name: ev-postgres
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_DB: ${POSTGRES_DB:-ev_charging}
|
||||
POSTGRES_USER: ${POSTGRES_USER:-evuser}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-evpass1234}
|
||||
ports:
|
||||
- "5432:5432"
|
||||
volumes:
|
||||
- pgdata:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-evuser}"]
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 5
|
||||
networks:
|
||||
- ev-net
|
||||
|
||||
# ── Redis ──
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
container_name: ev-redis
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "6375:6379"
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 5
|
||||
networks:
|
||||
- ev-net
|
||||
|
||||
volumes:
|
||||
pgdata:
|
||||
proxy_logs:
|
||||
proxy_config:
|
||||
|
||||
networks:
|
||||
ev-net:
|
||||
driver: bridge
|
||||
89
nginx/s1.byunc.com.conf
Normal file
89
nginx/s1.byunc.com.conf
Normal file
@@ -0,0 +1,89 @@
|
||||
server {
|
||||
#listen [::]:80;
|
||||
#root /var/www/html/mysite.com;
|
||||
index index.php index.html index.htm;
|
||||
server_name s1.byunc.com;
|
||||
|
||||
#error_log /var/log/nginx/mysite.com_error.log;
|
||||
#access_log /var/log/nginx/mysite.com_access.log;
|
||||
|
||||
client_max_body_size 16G;
|
||||
|
||||
location = / {
|
||||
return 302 /steve/;
|
||||
}
|
||||
|
||||
location /steve {
|
||||
proxy_pass http://192.168.0.126:8180;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
# ── FastAPI 대시보드 + API ──
|
||||
location = /dashboard {
|
||||
proxy_pass http://192.168.0.126:8000;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
location /api/ {
|
||||
proxy_pass http://192.168.0.126:8000;
|
||||
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;
|
||||
}
|
||||
|
||||
location /health {
|
||||
proxy_pass http://192.168.0.126:8000;
|
||||
}
|
||||
|
||||
# WebSocket 전용 설정 (핵심)
|
||||
location /steve/websocket {
|
||||
proxy_pass http://192.168.0.126:8180;
|
||||
|
||||
# WebSocket 업그레이드 헤더
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $host;
|
||||
|
||||
# WebSocket 타임아웃 (충전 중 끊기지 않게)
|
||||
proxy_read_timeout 86400s;
|
||||
proxy_send_timeout 86400s;
|
||||
proxy_connect_timeout 86400s;
|
||||
}
|
||||
location / {
|
||||
proxy_pass http://192.168.0.126:8180;
|
||||
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_redirect off;
|
||||
proxy_buffering off;
|
||||
proxy_read_timeout 86400s;
|
||||
proxy_send_timeout 86400s;
|
||||
proxy_connect_timeout 86400s;
|
||||
}
|
||||
listen 443 ssl; # managed by Certbot
|
||||
ssl_certificate /etc/letsencrypt/live/s1.byunc.com/fullchain.pem; # managed by Certbot
|
||||
ssl_certificate_key /etc/letsencrypt/live/s1.byunc.com/privkey.pem; # managed by Certbot
|
||||
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
|
||||
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
|
||||
|
||||
}
|
||||
server {
|
||||
if ($host = s1.byunc.com) {
|
||||
return 301 https://$host$request_uri;
|
||||
} # managed by Certbot
|
||||
|
||||
|
||||
server_name s1.byunc.com;
|
||||
listen 80;
|
||||
return 404; # managed by Certbot
|
||||
|
||||
|
||||
}
|
||||
25
steve/Dockerfile
Normal file
25
steve/Dockerfile
Normal file
@@ -0,0 +1,25 @@
|
||||
FROM eclipse-temurin:21-jdk
|
||||
|
||||
ENV LANG=C.UTF-8 LC_ALL=C.UTF-8
|
||||
|
||||
MAINTAINER Ling Li
|
||||
|
||||
# Download and install dockerize.
|
||||
# Needed so the web container will wait for MariaDB to start.
|
||||
ENV DOCKERIZE_VERSION v0.19.0
|
||||
RUN curl -sfL https://github.com/powerman/dockerize/releases/download/"$DOCKERIZE_VERSION"/dockerize-`uname -s`-`uname -m` | install /dev/stdin /usr/local/bin/dockerize
|
||||
|
||||
EXPOSE 8180
|
||||
EXPOSE 8443
|
||||
WORKDIR /code
|
||||
|
||||
VOLUME ["/code"]
|
||||
|
||||
# Copy the application's code
|
||||
COPY . /code
|
||||
|
||||
# Wait for the db to startup(via dockerize), then
|
||||
# Build and run steve, requires a db to be available on port 3306
|
||||
CMD dockerize -wait tcp://mariadb:3306 -timeout 60s && \
|
||||
./mvnw clean package -Pdocker,mariadb -Djdk.tls.client.protocols="TLSv1,TLSv1.1,TLSv1.2" && \
|
||||
java -XX:MaxRAMPercentage=85 -jar target/steve.war
|
||||
47
steve/JettyConfiguration.java
Normal file
47
steve/JettyConfiguration.java
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* SteVe - SteckdosenVerwaltung - https://github.com/steve-community/steve
|
||||
* Copyright (C) 2013-2026 SteVe Community Team
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.rwth.idsg.steve.config;
|
||||
|
||||
import org.eclipse.jetty.http.HttpCompliance;
|
||||
import org.eclipse.jetty.server.HttpConnectionFactory;
|
||||
import org.eclipse.jetty.server.ServerConnector;
|
||||
import org.springframework.boot.jetty.JettyServerCustomizer;
|
||||
import org.springframework.boot.jetty.servlet.JettyServletWebServerFactory;
|
||||
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class JettyConfiguration {
|
||||
|
||||
@Bean
|
||||
public WebServerFactoryCustomizer<JettyServletWebServerFactory> jettyHttpComplianceCustomizer() {
|
||||
return factory -> factory.addServerCustomizers((JettyServerCustomizer) server -> {
|
||||
for (var connector : server.getConnectors()) {
|
||||
if (connector instanceof ServerConnector serverConnector) {
|
||||
for (var cf : serverConnector.getConnectionFactories()) {
|
||||
if (cf instanceof HttpConnectionFactory httpCF) {
|
||||
httpCF.getHttpConfiguration().setHttpCompliance(HttpCompliance.RFC7230_LEGACY);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
66
steve/application-docker.properties
Normal file
66
steve/application-docker.properties
Normal file
@@ -0,0 +1,66 @@
|
||||
# Just to be backwards compatible with previous versions, this is set to "steve",
|
||||
# since there might be already configured chargepoints expecting the older path.
|
||||
# Otherwise, might as well be changed to something else or be left empty.
|
||||
#
|
||||
context.path = steve
|
||||
|
||||
# Database configuration
|
||||
#
|
||||
db.ip = mariadb
|
||||
db.port = 3306
|
||||
db.schema = stevedb
|
||||
db.user = steve
|
||||
db.password = changeme
|
||||
|
||||
# Credentials for Web interface access
|
||||
#
|
||||
auth.user = admin
|
||||
auth.password = 1234
|
||||
|
||||
# The header key and value for Web API access using API key authorization.
|
||||
# Both must be set for Web APIs to be enabled. Otherwise, we will block all calls.
|
||||
#
|
||||
webapi.key = STEVE-API-KEY
|
||||
webapi.value =
|
||||
|
||||
# Jetty configuration
|
||||
#
|
||||
server.host = 0.0.0.0
|
||||
server.gzip.enabled = false
|
||||
|
||||
# Jetty HTTP configuration
|
||||
#
|
||||
http.enabled = true
|
||||
http.port = 8180
|
||||
|
||||
# Jetty HTTPS configuration
|
||||
#
|
||||
https.enabled = false
|
||||
https.port = 8443
|
||||
keystore.path =
|
||||
keystore.password =
|
||||
|
||||
# When the WebSocket/Json charge point opens more than one WebSocket connection,
|
||||
# we need a mechanism/strategy to select one of them for outgoing requests.
|
||||
# For allowed values see de.rwth.idsg.steve.ocpp.ws.custom.WsSessionSelectStrategyEnum.
|
||||
#
|
||||
ws.session.select.strategy = ALWAYS_LAST
|
||||
|
||||
# if BootNotification messages arrive (SOAP) or WebSocket connection attempts are made (JSON) from unknown charging
|
||||
# stations, we reject these charging stations, because stations with these chargeBoxIds were NOT inserted into database
|
||||
# beforehand. by setting this property to true, this behaviour can be modified to automatically insert unknown
|
||||
# stations into database and accept their requests.
|
||||
#
|
||||
# CAUTION: setting this property to true is very dangerous, because we will accept EVERY BootNotification or WebSocket
|
||||
# connection attempt from ANY sender as long as the sender knows the URL and sends a valid message.
|
||||
#
|
||||
auto.register.unknown.stations = false
|
||||
|
||||
# if this field is set, it will take precedence over the default regex we are using in
|
||||
# de.rwth.idsg.steve.web.validation.ChargeBoxIdValidator.REGEX to validate the format of the chargeBoxId values
|
||||
#
|
||||
charge-box-id.validation.regex =
|
||||
|
||||
### DO NOT MODIFY ###
|
||||
db.sql.logging = false
|
||||
profile = prod
|
||||
31
steve/docker-compose.yml
Normal file
31
steve/docker-compose.yml
Normal file
@@ -0,0 +1,31 @@
|
||||
version: "3.0"
|
||||
|
||||
volumes:
|
||||
db-data:
|
||||
external: false
|
||||
|
||||
services:
|
||||
|
||||
db:
|
||||
image: mariadb:10.11.16
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- 3307:3306
|
||||
environment:
|
||||
MYSQL_RANDOM_ROOT_PASSWORD: "yes"
|
||||
MYSQL_DATABASE: stevedb
|
||||
MYSQL_USER: steve
|
||||
MYSQL_PASSWORD: changeme
|
||||
app:
|
||||
restart: unless-stopped
|
||||
build: .
|
||||
links:
|
||||
- "db:mariadb"
|
||||
volumes:
|
||||
- .:/code
|
||||
ports:
|
||||
- "8180:8180"
|
||||
- "8445:8443"
|
||||
depends_on:
|
||||
- db
|
||||
|
||||
Reference in New Issue
Block a user