Commit 78c35070 authored by 健杭 徐's avatar 健杭 徐
Browse files

docker

parent 4ab1ada5
FROM golang:1.24.3-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o /app/main .
FROM alpine:latest
WORKDIR /app
COPY --from=builder /app/main .
EXPOSE 8080
CMD ["/app/main"]
version: '3.8'
services:
backend:
build: .
ports:
- "8080:8080"
environment:
- DB_HOST=db
- DB_PORT=5432
- DB_USER=chat_room_user
- DB_PASSWORD=secure_password
- DB_NAME=chat_room_db
depends_on:
- db
db:
image: postgres:13-alpine
environment:
- POSTGRES_USER=chat_room_user
- POSTGRES_PASSWORD=secure_password
- POSTGRES_DB=chat_room_db
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:
...@@ -5,19 +5,29 @@ import ( ...@@ -5,19 +5,29 @@ import (
"fmt" "fmt"
"log" "log"
"net/http" "net/http"
"os"
"strconv" "strconv"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
_ "github.com/lib/pq" _ "github.com/lib/pq"
) )
const ( // Helper to get env var or default
host = "localhost" func getEnv(key, fallback string) string {
port = 5432 if value, ok := os.LookupEnv(key); ok {
user = "chat_room_user" return value
password = "secure_password" }
dbname = "chat_room_db" return fallback
) }
// Helper to get env var as int or default
func getEnvAsInt(name string, defaultVal int) int {
valueStr := getEnv(name, "")
if value, err := strconv.Atoi(valueStr); err == nil {
return value
}
return defaultVal
}
type Message struct { type Message struct {
MessageId int `json:"message_id"` MessageId int `json:"message_id"`
...@@ -49,6 +59,12 @@ type RoomAddRes struct { ...@@ -49,6 +59,12 @@ type RoomAddRes struct {
var db *sql.DB var db *sql.DB
func main() { func main() {
host := getEnv("DB_HOST", "localhost")
port := getEnvAsInt("DB_PORT", 5432)
user := getEnv("DB_USER", "chat_room_user")
password := getEnv("DB_PASSWORD", "secure_password")
dbname := getEnv("DB_NAME", "chat_room_db")
psqlInfo := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable", psqlInfo := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable",
host, port, user, password, dbname) host, port, user, password, dbname)
......
FROM node:18-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:18-alpine AS runner
WORKDIR /app
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT 3000
CMD ["node", "server.js"]
import type { NextConfig } from "next"; import type { NextConfig } from "next";
const nextConfig: NextConfig = { const nextConfig: NextConfig = {
/* config options here */ output: 'standalone',
}; };
export default nextConfig; export default nextConfig;
...@@ -209,7 +209,7 @@ ...@@ -209,7 +209,7 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
box-sizing: border-box; box-sizing: border-box;
background-image: url('../public/backGround.jpg'); background-color: #f0f0f0;
background-size: cover; background-size: cover;
z-index: 2; z-index: 2;
......
...@@ -242,7 +242,7 @@ function MessageItem (props: MessageProps & { onAddNewComment: (content: string) ...@@ -242,7 +242,7 @@ function MessageItem (props: MessageProps & { onAddNewComment: (content: string)
// From Uiverse.io by adamgiebl // From Uiverse.io by adamgiebl
} }
export function ChatRoomComponent({ userName }: { userName: string }) { function ChatRoomComponent({ userName }: { userName: string }) {
const [rooms, setRooms] = useState<RoomEntryProps[]>([]); const [rooms, setRooms] = useState<RoomEntryProps[]>([]);
const [currentRoom, setCurrentRoom] = useState<MessageProps | null>(null); const [currentRoom, setCurrentRoom] = useState<MessageProps | null>(null);
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
min-height: 100vh; min-height: 100vh;
width: 100vw; width: 100vw;
background-size: cover; background-size: cover;
background: url('../public/SetbackGround.jpg') no-repeat center; background-color: grey;
} }
.login-box .login-box
......
...@@ -3,14 +3,16 @@ ...@@ -3,14 +3,16 @@
import styles from"./Register.module.css" import styles from"./Register.module.css"
import { MdLock, MdPerson } from "react-icons/md"; import { MdLock, MdPerson } from "react-icons/md";
import { useState } from "react"; import { useState } from "react";
import { useRouter } from 'next/navigation';
const backEnd:string = "http://localhost:8080"; const backEnd:string = "http://localhost:8080";
export default function Register({ onLogin }: { onLogin: (name: string) => void }) { export default function Register() {
const [userName, setUserName] = useState(''); const [userName, setUserName] = useState('');
const [password, setPassword] = useState(''); const [password, setPassword] = useState('');
const [confirmPassword, setConfirmPassword] = useState(''); const [confirmPassword, setConfirmPassword] = useState('');
const [passwordError, setPasswordError] = useState(''); const [passwordError, setPasswordError] = useState('');
const router = useRouter();
const handleSubmit = async (e: React.FormEvent) => { const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault(); e.preventDefault();
...@@ -40,10 +42,11 @@ export default function Register({ onLogin }: { onLogin: (name: string) => void ...@@ -40,10 +42,11 @@ export default function Register({ onLogin }: { onLogin: (name: string) => void
throw new Error('Failed to register'); throw new Error('Failed to register');
} }
const data = await response.json(); alert('Registration successful! Redirecting to login page.');
onLogin(data.userName); router.push('/SetName');
} catch (error) { } catch (error) {
console.error(error); console.error(error);
setPasswordError('Registration failed. Please try again.');
} }
} }
return ( return (
...@@ -65,9 +68,9 @@ export default function Register({ onLogin }: { onLogin: (name: string) => void ...@@ -65,9 +68,9 @@ export default function Register({ onLogin }: { onLogin: (name: string) => void
<span className={styles["icon"]}> <span className={styles["icon"]}>
<MdLock /> <MdLock />
</span> </span>
<input <input
type="password" type="password"
required required
value={password} value={password}
onChange={(e) => setPassword(e.target.value)} /> onChange={(e) => setPassword(e.target.value)} />
<label>Password</label> <label>Password</label>
...@@ -76,9 +79,9 @@ export default function Register({ onLogin }: { onLogin: (name: string) => void ...@@ -76,9 +79,9 @@ export default function Register({ onLogin }: { onLogin: (name: string) => void
<span className={styles["icon"]}> <span className={styles["icon"]}>
<MdLock /> <MdLock />
</span> </span>
<input <input
type="password" type="password"
required required
value={confirmPassword} value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)} /> onChange={(e) => setConfirmPassword(e.target.value)} />
<label>Confirm Password</label> <label>Confirm Password</label>
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
min-height: 100vh; min-height: 100vh;
width: 100vw; width: 100vw;
background-size: cover; background-size: cover;
background: url('../public/SetbackGround.jpg') no-repeat center; background-color: grey;
} }
.login-box .login-box
......
...@@ -4,17 +4,18 @@ import styles from"./SetName.module.css" ...@@ -4,17 +4,18 @@ import styles from"./SetName.module.css"
import { MdLock, MdPerson } from "react-icons/md"; import { MdLock, MdPerson } from "react-icons/md";
import { useState } from "react"; import { useState } from "react";
import Link from "next/link"; import Link from "next/link";
import { useRouter } from 'next/navigation';
const backEnd:string = "http://localhost:8080"; const backEnd:string = "http://localhost:8080";
export default function SetName({ onLogin }: { onLogin: (name: string) => void }) { export default function SetName() {
const [userName, setUserName] = useState(''); const [userName, setUserName] = useState('');
const [password, setPassword] = useState(''); const [password, setPassword] = useState('');
const router = useRouter();
const handleSubmit = async (e: React.FormEvent) => { const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault(); e.preventDefault();
e.preventDefault();
try { try {
const response = await fetch(`${backEnd}/login`, { const response = await fetch(`${backEnd}/login`, {
method: "POST", method: "POST",
...@@ -26,12 +27,14 @@ export default function SetName({ onLogin }: { onLogin: (name: string) => void } ...@@ -26,12 +27,14 @@ export default function SetName({ onLogin }: { onLogin: (name: string) => void }
const data = await response.json(); const data = await response.json();
if (data.code === 0) { if (data.code === 0) {
onLogin(userName); localStorage.setItem('userName', userName);
router.push('/ChatRoom');
} else { } else {
alert(data.msg); alert(data.msg);
} }
} catch (error) { } catch (error) {
console.error("Error logging in:", error); console.error("Error logging in:", error);
alert("Login failed. Please check the console for details.");
} }
} }
return ( return (
...@@ -53,9 +56,9 @@ export default function SetName({ onLogin }: { onLogin: (name: string) => void } ...@@ -53,9 +56,9 @@ export default function SetName({ onLogin }: { onLogin: (name: string) => void }
<span className={styles["icon"]}> <span className={styles["icon"]}>
<MdLock /> <MdLock />
</span> </span>
<input <input
type="password" type="password"
required required
value={password} value={password}
onChange={(e) => setPassword(e.target.value)} /> onChange={(e) => setPassword(e.target.value)} />
<label>Password</label> <label>Password</label>
...@@ -70,4 +73,4 @@ export default function SetName({ onLogin }: { onLogin: (name: string) => void } ...@@ -70,4 +73,4 @@ export default function SetName({ onLogin }: { onLogin: (name: string) => void }
</div> </div>
</div> </div>
); );
} }
\ No newline at end of file
'use client'; 'use client';
import React from 'react'; import { useEffect } from 'react';
import SetName from './SetName/page';
import "./globals.css";
import { useRouter } from 'next/navigation'; import { useRouter } from 'next/navigation';
import "./globals.css";
export default function Page() { export default function Page() {
const router = useRouter(); const router = useRouter();
const handleLogin = (name: string) => { useEffect(() => {
localStorage.setItem('userName', name); router.replace('/SetName');
router.push('/ChatRoom'); }, [router]);
};
return ( return null;
<div className='root'>
<SetName onLogin={handleLogin} />
</div>
);
} }
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment