[๊ฐ์] ๋ฐ๋ผํ๋ฉฐ ๋ฐฐ์ฐ๋ ๋์ปค์ CIํ๊ฒฝ -6
์ด์ : ํ๋ก ํธ๋ง ์ฌ์ฉ
์ด๋ฒ : ๋ฐฑ์๋์ DB๋ ๊ตฌํํด์ ๋ง์ ์ปจํ ์ด๋ ์ฌ์ฉ
๋ ๊ฐ์ง ๋ฐฉ์์ผ๋ก ์ค๊ณ ๊ฐ๋ฅ -> ์ฒซ ๋ฒ์งธ ๋ฐฉ์์ผ๋ก ๊ฐ์ ์งํ
- Nginx์ Proxy๋ฅผ ์ด์ฉํ ์ค๊ณ
- Nginx๋ ์ ์ ํ์ผ์ ์ ๊ณต๋ง ํด์ฃผ๋ ์ค๊ณ
ํฐ๊ทธ๋ฆผ
๐ซNode JS ๊ตฌ์ฑํ๊ธฐ
backendํด๋ ๋ง๋ค๊ณ ์ฌ๊ธฐ์ npm init
nodemon์ ์ฌ์ฉํ๋ ์ด์ : ๋ ธ๋ ์ฝ๋๋ฅผ ๋ณ๊ฒฝํด๋ ๋ฐ๋ก ์ค๋จ, ์ฌ๊ฐ๋ ์์ผ์ค ์ ์๋๋ก ํ๊ธฐ ์ํด
db.js
const mysql = require("mysql");
const pool = mysql.createPool({
connectionLimit: 10,
host: 'mysql',
user: 'root',
password: 'johnahn',
database: 'myapp'
});
exports.pool = pool;
server.js
const express = require("express");
const bodyParser = require('body-parser');
const db = require('./db');
const app = express();
app.user(bodyParser.json());
db.pool.query(`CREATE TABLE lists (
id INTEGER AUTO_INCREMENT,
value TEXT,
PRIMARY KEY (id))`,
(err, results, fileds) => {
console.log('results', results)
})
ap.get('/api/values', function (req, res) {
db.pool.query(`SELECT * FROM lists;`,
(err, results, fileds) => {
if (err)
return res.status(500).send(err)
else
return res.json({ success: true, value: req.body.value })
}
})
ap.post('/api/values', function (req, res, next) {
db.pool.query(`INSERT INTO lists (vlaue) VALUES("${req.body.value}"))`,
(err, results, fileds) => {
if (err)
return res.status(500).send(err)
else
return res.json({ success: true, value: req.body.value })
}
})
app.listen(5000, () => {
console.log('์ดํ๋ฆฌ์ผ์ด์
์ด ์๋ฒ 5000๋ฒ ํฌํธ์์ ์์๋์์ต๋๋ค.')
})
๐ซReact JS ๊ตฌ์ฑํ๊ธฐ
frontend ํด๋ ์์ฑ
npx create-react-app frontend ๋ช ๋ น์ด๋ก react ํ์ผ ์์ฑ
App.js
axios ์๋ผ์ ํ์ฐธ ํค๋งค๋ค ์ง์ ์ค์นํ๋๋ฐ ๋ด๊ฐ์์ ์๋ชป๋๋ค๊ณ ์๋ ค์ฃผ์ฌ ๊ฐํน๋ฐ๋๋ค
import logo from './logo.svg';
import './App.css';
import React, { useState, useEffect } from 'react';
import axios from 'axios';
function App() {
useEffect(() => {
axios.get(`/api/values`)
.then(response => {
console.log('response', response.data)
setLists(response.data)
})
}, [])
const [lists, setLists] = useState([])
const [value, setValue] = useState("")
const changeHandler = (event) => {
setValue(event.currentTarget.value)
}
const submitHandler = (event) => {
event.preventDefault();
axios.post(`/api/value`,
{ value: value })
.then(response => {
if (response.data.success) {
console.log('response.data', response.data)
setLists([...lists, response.data])
setValue("");
} else {
alert("๊ฐ์ DB์ ๋ฃ๋๋ฐ ์คํจํ์ต๋๋ค.")
}
})
}
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<div className="container">
{lists && lists.map((list, index) => (
<li key={index}>{list.value}</li>
))}
<form className="example" onSubmit={submitHandler}>
<input
type="text"
placeholder="์
๋ ฅํด์ฃผ์ธ์..."
onchange={changeHandler}
value={value}
/>
<button type="submit">ํ์ธ</button>
</form>
</div>
</header>
</div>
);
}
export default App;
๐ณ for ๋ฆฌ์กํธ ์ฑ ๋์ปค ํ์ผ ๋ง๋ค๊ธฐ
default.conf ๋ฅผ ์ด์์์ฌ index.html์ด home์ด๋ผ๋ ๊ฒ์ ์๋ ค์ค๋ค
server{
listen 3000;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
}
Dockerfile
FROM node:alpine as builder
WORKDIR /app
COPY ./package.json ./
RUN npm install
COPY ./ ./
RUN npm run build
FROM nginx
EXPOSE 3000
COPY ./nginx/default.conf /etc/nginx/conf.d/default.conf
COPY --from=builder /app/build /usr/share/nginx/html
๐ณ for ๋ ธ๋ ์ฑ ๋์ปค ํ์ผ ๋ง๋ค๊ธฐ
mysql ํด๋ ์์ฑ
Dockerfile.dev
์ ํ์ผ๊ณผ "start"->"dev"ํ๋ ์ฐจ์ด
Dockerfile
Dockerfile.dev์์ "start"๋ง ๊ทธ๋๋ก ๋
๐ณ for MySQL ๋์ปค ํ์ผ ๋ง๋ค๊ธฐ
Dockerfile
FROM mysql:5.7
ADD ./my.cnf /etc/mysql/conf.d/my.cnf
my.cnf
ํ๊ธ ๊นจ์ง ํ์ ๋ฐฉ์ง ์ํจ
initialize.sql
DROP DATABASE IF EXIST myapp;
CREATE DATABASE myapp;
USE myapp;
CREATE TABLE lists(
id INTEGER AUTO_INCREMENT,
value TEXT,
PRIMARY KEY (id)
)
๐ณ for Nginx ๋์ปค ํ์ผ ๋ง๋ค๊ธฐ
nginx ํด๋ ์์ฑ
ํด๋ผ์ด์ธํธ ์์ฒญ์ ๋ฐ๋ผ ์ ์ ํ์ผ์ ์ํ๋ฉด React.js API ์์ฒญ์ด๋ฉด Node.js๋ก ๋ณด๋ธ๋ค.
->๊ธฐ์ค: /api๋ก ์์ํ๋์ง, /๋ก ์์ํ๋์ง
default.conf
React.js๋ก ๋ณด๋ผ ๊ฒ๊ณผ Node.js๋ก ๋ณด๋ผ ๊ฒ ๋ถ๋ฆฌ
Dockerfile
FROM nginx
COPY ./default.conf /etc/nginx/conf.d/default.conf
๐ Docker Compose ํ์ผ ์์ฑํ๊ธฐ
version: "3"
services:
frontend:
build:
context: ./frontend
dockerfile: Dockerfile.dev
volumes:
- /app/node_modules
- ./frontend:/app
stdin_open: true
nginx:
restart : always #์ฌ์์ ์ ์ฑ
, ํญ์ ์ฌ์์
build:
context: ./nginx
dockerfile: Dockerfile
ports:
- "3000:80"
backend:
build:
context: ./backend
dockerfile: Dockerfile.dev
container_name: app_backend
volumes:
- /app/node_modules
- ./backend:/app
mysql:
build: ./mysql
restart: unless-stopped #๊ฐ๋ฐ์๊ฐ ์์๋ก ๋ฉ์ถ๋ ค๊ณ ํ๋๊ฑฐ ์๋๋ฉด ํญ์ ์ฌ์์
container_name: app_mysql
ports:
- "3306:3306"
volumes:
- ./mysql/mysql_data:/var/lib/mysql
- ./mysql/sqls/:/docker-entrypoint-initdb.d/
environment:
MYSQL_ROOT_PASSWORD: johnahn
MYSQL_DATABASE: myapp
docker-compose up ์ผ๋ก ์คํ
๋นก๋๊ฐ๋ฆฌ์ ์ค๋ฅ์ผ๊ธฐ
1. nginx ์คํ ๋ง ํ๋ฆผ nginix๋ผ๊ณ ์คํ๋(์์ง๋์ค ๋ง์๋..)
2. "3306":"3306" ํจ
3. ์ฃผ์๋ค๋๋ผ ํ๊ธ ์จ๋๊ณ utf-8๋ก ์ ์ฅ ์ํจ
๐ Volume์ ์ด์ฉํ ๋ฐ์ดํฐ ๋ฒ ์ด์ค ๋ฐ์ดํฐ ์ ์งํ๊ธฐ
์ด์ : ์ปจํ ์ด๋ ๋ด๋ถ์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ฒ ๋๋ฏ๋ก, ์ปจํ ์ด๋ ์ญ์ ์ ์ปจํ ์ด๋ ์์ ์ ์ฅ๋ ๋ฐ์ดํฐ๋ ํจ๊ป ์ญ์ ๋๋ค.
-> ์์์ฑ์ด ํ์ํ ๋ฐ์ดํฐ๋? -> Volumes
ํธ์คํธ ํ์ผ ์์คํ ์ ๋์ปค์ ์ํด์๋ง ํต์ ๋๋ ๋์ปค Area์ ๋ฐ์ดํฐ๊ฐ ์ ์ฅ๋๋ค
-> ๋ฐ์ดํฐ๊ฐ ์ฌ๋ผ์ง์ง ์๋๋ค.