Fix: Handle .env directory issue in bind mount and use relative API paths for single container
This commit is contained in:
@@ -31,6 +31,8 @@ services:
|
||||
- oltalama-logs:/app/backend/logs
|
||||
# .env file (optional bind mount - host'tan container'a)
|
||||
# Eğer host'ta .env yoksa, entrypoint script container içinde oluşturur
|
||||
# NOT: Host'ta .env dosyası yoksa, Docker onu dizin olarak oluşturabilir
|
||||
# Entrypoint script bunu otomatik düzeltir
|
||||
- ./backend/.env:/app/backend/.env:rw
|
||||
healthcheck:
|
||||
test: ["CMD", "node", "-e", "require('http').get('http://localhost:3000/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"]
|
||||
|
||||
@@ -27,18 +27,29 @@ if [ -z "$SESSION_SECRET" ] || [ "$SESSION_SECRET" = "change-this-to-a-very-stro
|
||||
SESSION_SECRET=$(node -e "console.log(require('crypto').randomBytes(64).toString('hex'))")
|
||||
export SESSION_SECRET
|
||||
|
||||
# .env dosyası yolu
|
||||
ENV_FILE="/app/backend/.env"
|
||||
|
||||
# Eğer .env bir dizin ise (bind mount sorunu), sil ve dosya olarak oluştur
|
||||
if [ -d "$ENV_FILE" ]; then
|
||||
echo "⚠️ .env bir dizin olarak tespit edildi, düzeltiliyor..."
|
||||
rm -rf "$ENV_FILE"
|
||||
fi
|
||||
|
||||
# .env dizinini oluştur (yoksa)
|
||||
mkdir -p "$(dirname "$ENV_FILE")"
|
||||
|
||||
# Session secret'ı .env dosyasına kaydet (persist)
|
||||
if [ ! -f "/app/backend/.env" ]; then
|
||||
mkdir -p /app/backend
|
||||
echo "SESSION_SECRET=$SESSION_SECRET" > /app/backend/.env
|
||||
if [ ! -f "$ENV_FILE" ]; then
|
||||
echo "SESSION_SECRET=$SESSION_SECRET" > "$ENV_FILE"
|
||||
echo "✅ Yeni SESSION_SECRET oluşturuldu ve .env dosyasına kaydedildi"
|
||||
echo "📝 SESSION_SECRET: ${SESSION_SECRET:0:20}... (ilk 20 karakter)"
|
||||
else
|
||||
# Mevcut .env dosyasını güncelle
|
||||
if grep -q "^SESSION_SECRET=" /app/backend/.env; then
|
||||
sed -i "s|^SESSION_SECRET=.*|SESSION_SECRET=$SESSION_SECRET|" /app/backend/.env
|
||||
if grep -q "^SESSION_SECRET=" "$ENV_FILE"; then
|
||||
sed -i "s|^SESSION_SECRET=.*|SESSION_SECRET=$SESSION_SECRET|" "$ENV_FILE"
|
||||
else
|
||||
echo "SESSION_SECRET=$SESSION_SECRET" >> /app/backend/.env
|
||||
echo "SESSION_SECRET=$SESSION_SECRET" >> "$ENV_FILE"
|
||||
fi
|
||||
echo "✅ SESSION_SECRET güncellendi ve .env dosyasına kaydedildi"
|
||||
fi
|
||||
|
||||
@@ -13,9 +13,7 @@ import {
|
||||
Grid,
|
||||
} from '@mui/material';
|
||||
import { Save, Send } from '@mui/icons-material';
|
||||
import axios from 'axios';
|
||||
|
||||
const API_URL = import.meta.env.VITE_API_URL;
|
||||
import api from '../services/api';
|
||||
|
||||
function Settings() {
|
||||
const [settings, setSettings] = useState({
|
||||
@@ -49,9 +47,7 @@ function Settings() {
|
||||
|
||||
const loadSettings = async () => {
|
||||
try {
|
||||
const response = await axios.get(`${API_URL}/api/settings`, {
|
||||
withCredentials: true,
|
||||
});
|
||||
const response = await api.get('/api/settings');
|
||||
const data = response.data.data || {};
|
||||
|
||||
// Convert array to object
|
||||
@@ -83,9 +79,7 @@ function Settings() {
|
||||
|
||||
const loadAdminInfo = async () => {
|
||||
try {
|
||||
const response = await axios.get(`${API_URL}/api/settings/admin`, {
|
||||
withCredentials: true,
|
||||
});
|
||||
const response = await api.get('/api/settings/admin');
|
||||
if (response.data.success && response.data.data) {
|
||||
setAdminInfo({
|
||||
username: response.data.data.username || '',
|
||||
@@ -102,21 +96,21 @@ function Settings() {
|
||||
const handleSave = async () => {
|
||||
try {
|
||||
await Promise.all([
|
||||
axios.put(`${API_URL}/api/settings/system`, {
|
||||
api.put('/api/settings/system', {
|
||||
base_url: settings.base_url,
|
||||
frontend_url: settings.frontend_url,
|
||||
cors_enabled: settings.cors_enabled,
|
||||
}, { withCredentials: true }),
|
||||
axios.put(`${API_URL}/api/settings/gmail`, {
|
||||
api.put('/api/settings/gmail', {
|
||||
gmail_user: settings.gmail_user,
|
||||
gmail_app_password: settings.gmail_app_password,
|
||||
gmail_from_name: settings.gmail_from_name,
|
||||
}, { withCredentials: true }),
|
||||
axios.put(`${API_URL}/api/settings/telegram`, {
|
||||
api.put('/api/settings/telegram', {
|
||||
telegram_bot_token: settings.telegram_bot_token,
|
||||
telegram_chat_id: settings.telegram_chat_id,
|
||||
}, { withCredentials: true }),
|
||||
axios.put(`${API_URL}/api/ollama/settings`, {
|
||||
api.put('/api/ollama/settings', {
|
||||
ollama_server_url: settings.ollama_server_url,
|
||||
ollama_model: settings.ollama_model,
|
||||
}, { withCredentials: true }),
|
||||
@@ -131,11 +125,7 @@ function Settings() {
|
||||
const handleTestMail = async () => {
|
||||
setTestLoading({ ...testLoading, mail: true });
|
||||
try {
|
||||
const response = await axios.post(
|
||||
`${API_URL}/api/settings/test-gmail`,
|
||||
{},
|
||||
{ withCredentials: true }
|
||||
);
|
||||
const response = await api.post('/api/settings/test-gmail', {});
|
||||
setAlerts({ ...alerts, mail: { severity: 'success', message: response.data.message } });
|
||||
} catch (error) {
|
||||
setAlerts({
|
||||
@@ -150,11 +140,7 @@ function Settings() {
|
||||
const handleTestTelegram = async () => {
|
||||
setTestLoading({ ...testLoading, telegram: true });
|
||||
try {
|
||||
const response = await axios.post(
|
||||
`${API_URL}/api/settings/test-telegram`,
|
||||
{},
|
||||
{ withCredentials: true }
|
||||
);
|
||||
const response = await api.post('/api/settings/test-telegram', {});
|
||||
setAlerts({ ...alerts, telegram: { severity: 'success', message: response.data.message } });
|
||||
} catch (error) {
|
||||
setAlerts({
|
||||
@@ -182,10 +168,7 @@ function Settings() {
|
||||
}, { withCredentials: true });
|
||||
}
|
||||
|
||||
const response = await axios.get(
|
||||
`${API_URL}/api/ollama/test`,
|
||||
{ withCredentials: true }
|
||||
);
|
||||
const response = await api.get('/api/ollama/test');
|
||||
|
||||
if (response.data.success) {
|
||||
setOllamaModels(response.data.data.models || []);
|
||||
@@ -233,11 +216,7 @@ function Settings() {
|
||||
updateData.current_password = adminInfo.current_password;
|
||||
}
|
||||
|
||||
const response = await axios.put(
|
||||
`${API_URL}/api/settings/admin`,
|
||||
updateData,
|
||||
{ withCredentials: true }
|
||||
);
|
||||
const response = await api.put('/api/settings/admin', updateData);
|
||||
|
||||
if (response.data.success) {
|
||||
setAlerts({
|
||||
|
||||
@@ -1,6 +1,26 @@
|
||||
import axios from 'axios';
|
||||
|
||||
const API_URL = import.meta.env.VITE_API_URL || 'http://localhost:3000';
|
||||
// Single container setup: Use relative path (same origin)
|
||||
// Multi-container setup: Use VITE_API_URL or default to localhost:3000
|
||||
const getApiUrl = () => {
|
||||
const envUrl = import.meta.env.VITE_API_URL;
|
||||
|
||||
// If VITE_API_URL is set, use it
|
||||
if (envUrl) {
|
||||
return envUrl;
|
||||
}
|
||||
|
||||
// Single container: same origin, use relative path
|
||||
// This works because frontend and backend are served from the same port
|
||||
if (import.meta.env.PROD) {
|
||||
return ''; // Relative path - same origin
|
||||
}
|
||||
|
||||
// Development: default to localhost:3000
|
||||
return 'http://localhost:3000';
|
||||
};
|
||||
|
||||
const API_URL = getApiUrl();
|
||||
|
||||
const api = axios.create({
|
||||
baseURL: API_URL,
|
||||
|
||||
Reference in New Issue
Block a user