
Mysql์ด ์ด์ ๋ ๋์ปค ์์์ ๋์๊ฐ๋ ๊ฒ ์๋ AWS์์ ๋์๊ฐ๊ณ ์๋ ๊ฒ์ ์ฐ๋ฆฌ์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฐ๊ฒฐ๋ง ํด์ค ๊ฒ์ด๋ Mysql์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฐ๊ฒฐํด์ฃผ๋ ๋ถ๋ถ ๋นผ๊ณ ๋ค ์ง์์ค๋ค.
๊นํ์ Master ๋ธ๋์น์ ์๋ก ์ ๋ฐ์ดํธ๋ ์์ค๊ฐ ์ฌ๋ผ์๋ค๋ฉด์ด์ ๋ ๊ทธ ์์ค๋ฅผ Travis CI์์ ๊ฐ์ ธ์์ค์ผ ํฉ๋๋ค.
๊นํ๋ธ์ ์ฝ๋๋ฅผ ํธ์
โ Travis CI๊ฐ ์๋์ผ๋ก ์ฝ๋๋ฅผ ๊ฐ์ ธ์ด
โ ๊ฐ์ ธ์จ ์ฝ๋๋ก ํ ์คํธ์ฝ๋๋ฅผ ์คํ
โ ์ฑ๊ณตํ๋ฉด ์ด์ํ๊ฒฝ์ ์ด๋ฏธ์ง๋ฅผ ๋น๋
โ ๋น๋๋ ์ด๋ฏธ์ง๋ฅผ ๋์ปค ํ๋ธ๋ก ์ ์ก
โ AWS EB์ DockerHub์ ์ด๋ฏธ์ง๋ฅผ ๋ณด๋๋ค๊ณ ์๋ฆผ
โ AWS EB์์ DockerHub์ ์๋ ์ด๋ฏธ์ง๋ฅผ ๊ฐ์ ธ์จ ํ์ ๋ฐฐํฌ๋ฅผ ํ๋ค.
language: generic
sudo: required
services:
- docker
before_install:
- docker build -t kkkkmd/react-test-app -f ./frontend/Dockerfile.dev ./frontend
script:
- docker run -e CI=true kkkkmd/react-test-app npm test
after_success:
#๊ฐ๊ฐ์ ์ด๋ฏธ์ง๋ฅผ ๋น๋ํ๊ธฐ
- docker build -t kkkkmd/docker-frontend ./frontend
- docker build -t kkkkmd/docker-backend ./backend
- docker build -t kkkkmd/docker-nginx ./nginx
#๋์ปค ํ๋ธ์ ๋ก๊ทธ์ธ
- echo "$DOCKER_HUB_PASSWORD" | docker login -u "$DOCKER_HUB_ID" --password-stdin
#๋น๋ ๋ ์ด๋ฏธ์ง๋ค์ ๋์ปค ํ๋ธ์ Push ํ๊ธฐ
- docker push kkkkmd/docker-frontend
- docker push kkkkmd/docker-backend
- docker push kkkkmd/docker-nginx
์ด์ ์ travis ci ์ค์ตํ ๋๋ ์ ์ด๋จ์ง๋ง ํ๋ฒ๋ ๊ฐ๊ฐ์ ์ฝ๋๊ฐ ๋ฌด์์ ์๋ฏธํ๋์ง ์จ๋ณธ๋ค.
language : ์ธ์ด ํ๋ซํผ ์ ํsudo : ๊ด๋ฆฌ์ ๊ถํ๊ฐ๊ธฐservices : ๋์ปค ํ๊ฒฝ ๊ตฌ์ฑbefore_install : ์คํฌ๋ฆฝํธ๋ฅผ ์คํํ ์ ์๋ ํ๊ฒฝ ๊ตฌ์ฑbefore_install:
- docker build -t kkkkmd/react-test-app -f ./frontend/Dockerfile.dev ./frontend โ docker build -t <๋์ปค ์์ด๋> / <์ดํ์ด๋ฆ> -f <Dockerfile ๊ฒฝ๋ก> <๋น๋ํด์ผํ ํ์ผ๋ค์ด ์๋ ๊ฒฝ๋ก>script : ์คํํ ์คํฌ๋ฆฝํธ(ํ
์คํธ ์คํ)after_success : ํ
์คํธ ์ฑ๊ณต ํ ํ ์ผTravis CI์์ ๋ด๊ฐ ์ด travis.yml ์ฝ๋๋ฅผ ๋ฃ์ด์ค ๋ ํ์งํ ๋ฆฌ settings๋ฅผ ๋ค์ด๊ฐ Docker hub ์์ด๋์ ๋น๋ฒ์ ๋ง๋ค์ด์ฃผ์, ์ ๋ฒ์ ํ๋ aws secret key ์ค์ ๋ฐฉ๋ฒ๊ณผ ๊ฐ๋ค.
์ด๋ ๊ฒ ํ๊ณ ๊นํ๋ธ ๋ ํ์งํ ๋ฆฌ์ ๋ฃ์ด์ค ํ Travis ci์์ ํ์ธํด๋ณด๋ฉด
log๊ฐ ์ญ์ฃฝ์ญ ๋์ค๋ค๊ฐ ๋ง์ง๋ง์ ์ ๋ ๊ฒ push๊ฐ ์ ๋ ๊ฒ์ ํ์ธ ํ ์ ์์๋ค.

์ ๋ฒ ์ค์ต์์๋ ๋ฆฌ์กํธ๋ง์ ์ด์ฉํด์ ์ฑ์ ๋ง๋ค ๋๋ Dockerrun.aws.json์ด๋ผ๋ ํ์ผ์ ์ฌ์ฉํ์ง ์์์๋๋ฐ ์ด๋ฒ์๋ ์ด ํ์ผ์ ์จ์ผ์ง ElastickBeanstalk์์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์๋์ ์ํฌ ์ ์๋ค.
๋์ปค ํ์ผ์ด ํ๋๋ง ํ์ํ ๋,(๋ฆฌ์กํธ ์ ํ๋ฆฌ์ผ์ด์ )

์ ๋ฒ์ ๋ฆฌ์กํธ๋ง์ ์ด์ฉํ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ง๋ค ๋๋ Dockerfile์ด ํ๋์๋ค.
๊ทธ๋์ ๊ทธ ๋์ปค ํ์ผ์ Elastic beanstalk์ ์ ๋ฌํ๋ฉด EB๊ฐ ์์์ ์ด๋ฏธ์ง๋ฅผ ๋น๋ํ๊ณ ๊ทธ ๋น๋๋ ์ด๋ฏธ์ง๋ฅผ ๋๋ ค์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์คํํ์์๋๋ฐ ์๋ฌด๋ฐ ์ค์ ์ ์ฐ๋ฆฌ๊ฐ ํด์ฃผ์ง ์์๋ ๋์์.
UI๋ง ์ฒ๋ฆฌํ์์ผ๋๊น!

ํ์ง๋ง ์ด๋ฒ์๋ ๋
ธ๋, Mysql, Nginx ๋ฑ์ ์ํ Dockerfile์ด ์ฌ๋ฟ ์๋ค. ๊ทธ๋ฌ๊ธฐ์ EB๊ฐ ์ด๋ค ํ์ผ์ ๋จผ์ ์คํํ๊ณ ์ด๋ป๊ฒ ํ๋์ ์ทจํด์ผ ํ๋์ง ์๋์ผ๋ก ํ๋ก์ธ์ค๋ฅผ ํด๋๊ฐ ์ ์๊ธฐ ๋๋ฌธ์ ์ฐ๋ฆฌ๊ฐ ์์๋ก ์ค์ ์ ํด์ค์ผ ํ๋ค.
๊ทธ๊ฑธ ์ค์ ํด์ฃผ๋ ํ์ผ์ด ๋ฐ๋ก Dockerrun.aws.json!
AWS์์ ๋งํ๋ Dockerrun.aws.json ํ์ผ์ ์ ์
Dockerrun.aws.jsonย ํ์ผ์ Docker ์ปจํ ์ด๋ ์ธํธ๋ฅผ Elastic Beanstalk ์ ํ๋ฆฌ์ผ์ด์ ์ผ๋ก ๋ฐฐํฌํ๋ ๋ฐฉ๋ฒ์ ์ค๋ช ํ๋ Elastic Beanstalk ๊ณ ์ ์ JSON ํ์ผ์ ๋๋ค.ยDockerrun.aws.jsonย ํ์ผ์ ๋ฉํฐ์ปจํ ์ด๋ Docker ํ๊ฒฝ์ ์ฌ์ฉํ ์ ์์ต๋๋ค
Dockerrun.aws.json์ ํ๊ฒฝ์์ ๊ฐ ์ปจํ ์ด๋ ์ธ์คํด์ค(Docker ์ปจํ ์ด๋๋ฅผ ํธ์คํธํ๋ Amazon EC2 ์ธ์คํด์ค)์ ๋ฐฐํฌํ ์ปจํ ์ด๋ ๋ฐ ํ์ฌํ ์ปจํ ์ด๋์ ํธ์คํธ ์ธ์คํด์ค์์ ์์ฑํ ๋ฐ์ดํฐ ๋ณผ๋ฅจ์ ์ค๋ช ํฉ๋๋ค.
Dockerrun.aws.json โ (์ด๋ป๊ฒ ๋ค์ค ์ปจํ
์ด๋๋ฅผ ์๋์ํฌ์ง ์๋ ค์ค) โ> ์ผ๋ผ์คํฑ ๋น์คํกDockerrun.aws.json์ ์๋ ๊ตฌ์กฐ
AWS์์ ๋งํ๋ Task Definition(์์ ์ ์)์์ ์ง์ ํ ์ ์๋ ๊ฒ๋ค
- ์์ ์ ๊ฐ ์ปจํ ์ด๋์ ์ฌ์ฉํ ๋์ปค ์ด๋ฏธ์ง
- ๊ฐ ์์ ๋๋ ์์ ๋ด ๊ฐ ์ปจํ ์ด๋์์ ์ฌ์ฉํ CPU ๋ฐ ๋ฉ๋ชจ๋ฆฌ์ ์
- ์ฌ์ฉํ ์์ ์ ํ์ผ๋ก์ ํด๋น ์์ ์ด ํธ์คํ ๋๋ ์ธํ๋ผ๋ฅผ ๊ฒฐ์
- ์์ ์ ์ปจํ ์ด๋์ ์ฌ์ฉํ ๋์ปค ๋คํธ์ํน ๋ชจ๋
- ์์ ์ ์ฌ์ฉํ ๋ก๊น ๊ตฌ์ฑ
- ์ปจํ ์ด๋๊ฐ ์ข ๋ฃ ๋๋ ์คํจํ๋๋ผ๋ ์์ ์ด ๊ณ์ ์คํ๋ ์ง ์ฌ๋ถ
- ์ปจํ ์ด๋ ์์ ์ ์ปจํ ์ด๋๊ฐ ์คํํ ๋ช ๋ น
- ์์ ์ ์ปจํ ์ด๋์์ ์ฌ์ฉํ ๋ฐ์ดํฐ ๋ณผ๋ฅจ
- ์์ ์์ ์ฌ์ฉํด์ผ ํ๋ IAM ์ญํ

{
"AWSEBDockerrunVersion": 2,
"containerDefinitions": [
{
"name": "frontend",
"image": "smileajw1004/docker-frontend",
"hostname": "frontend",
"essential": false,
"memory": 128
},
{
"name": "backend",
"image": "smileajw1004/docker-backend",
"hostname": "backend",
"essential": false,
"memory": 128
},
{
"name": "nginx",
"image": "smileajw1004/docker-nginx",
"hostname": "nginx",
"essential": true,
"portMappings": [
{
"hostPort": 80,
"containerPort": 80
}
],
"links": ["frontend", "backend"],
"memory": 128
}
]
}
AWSEBDockerrunVersion : Dockerrun ๋ฒ์ 2๋ก ์ง์ containerDefinitions : ์ด ์์์ ์ปจํ
์ด๋๋ค์ ์ ์.
.
{
"name": "frontend",
"image": "smileajw1004/docker-frontend",
"hostname": "frontend",
"essential": false,
"memory": 128
},
.
.
name : ์ปจํ
์ด๋์ ์ด๋ฆimage : Docker ์ปจํ
์ด๋๋ฅผ ๊ตฌ์ถํ ์จ๋ผ์ธ Docker ๋ฆฌํฌ์งํ ๋ฆฌ์ Docker ์ด๋ฏธ์ง ์ด๋ฆhostname : ํธ์คํธ ์ด๋ฆ, ์ด ์ด๋ฆ์ ์ด์ฉํด์ ๋์ปค ์ปดํฌ์ฆ๋ฅผ์ด์ฉํด ์์ฑ๋ ๋ค๋ฅธ ์ปจํ
์ด๋์์์ ๊ทผ์ด ๊ฐ๋ฅessential : ์ปจํ
์ด๋๊ฐ ์คํจํ ๊ฒฝ์ฐ ์์
์ ์ค์งํด์ผ ํ๋ฉด true์
๋๋ค. ํ์์ ์ด์ง ์์ ์ปจํ
์ด๋๋ ์ธ์คํด์ค์ ๋๋จธ์ง ์ปจํ
์ด๋์ ์ํฅ์ ๋ฏธ์น์ง ์๊ณ ์ข
๋ฃ๋๊ฑฐ๋ ์ถฉ๋ํ ์ ์์memory : ์ปจํ
์ด๋์ฉ์ผ๋ก ์์ฝํ ์ปจํ
์ด๋ ์ธ์คํด์ค์ ์๋ ๋ฉ๋ชจ๋ฆฌ ์, ์ปจํ
์ด๋ ์ ์์์ memory ๋๋ memoryReservation ํ๋ผ๋ฏธํฐ ์ค ํ๋ ๋๋ ๋ชจ๋์ 0์ด ์๋ ์ ์๋ฅผ ์ง์ ํ๋ฉด ๋จportMappings : ์ปจํ
์ด๋์ ์๋ ๋คํธ์ํฌ ์ง์ ์ ํธ์คํธ์ ์๋ ์ง์ ์ ๋งคํlinks : ์ฐ๊ฒฐํ ์ปจํ
์ด๋์ ๋ชฉ๋ก์
๋๋ค. ์ฐ๊ฒฐ๋ ์ปจํ
์ด๋๋ ์๋ก๋ฅผ ๊ฒ์ํ๊ณ ์์ ํ๊ฒ ํต์ ํ ์ ์์Nginx์ VPC์ Security Group์ ์ค์ ํด ์ค์ผ ํ๋?
RDS๋ฅผ ์์ฑํด์ค์ผํ๋๋ฐ docker-compose๋ถ๋ถ์ DB์ ์ํ ํ๊ฒฝ๋ณ์๋ฅผ ๋ฃ์ด์ค๋ค.
์ฆ, ์ฝ๋๋ฅผ ์์ ํด์ฃผ๋ฉด ๋๋๋ฐ..
์ฐ์ db.js๋ฅผ ์์ ํด์ค๋ค.
//db.js
const mysql = require("mysql");
const pool = mysql.createPool({
connectionLimit: 10,
host: process.env.MYSQL_HOST,
user: process.env.MYSQL_USER,
password: process.env.MYSQL_ROOT_PASSWORD,
database: process.env.MYSQL_DATABASE,
port: process.env.MYSQL_PORT
});
exports.pool = pool;
docker-compose.yml๋ ์์ ํ๋ฉด ๋๋ค.
#docker-compose.yml
backend:
build:
dockerfile: Dockerfile.dev
context: ./backend
container_name: app_backend
volumes:
- /app/node_modules
- ./backend:/app
environment:
MYSQL_HOST: mysql
MYSQL_USER: root
MYSQL_ROOT_PASSWORD: seongeun
MYSQL_DATABASE: myapp
MYSQL_PORT: 3307
์ด๋ VPC์์ ๋ณด์๊ทธ๋ฃน์ผ๋ก ๋ค์ด๊ฐ์ ์์ฑํด์ฃผ๋ฉด ๋๋ค.
๋ง๋ ํ์ ์ฌ๊ธฐ์ ์ธ๋ฐ์ด๋ ๊ท์น ์ค์ ์ด ํ์ํ๋ค.
์ธ๋ฐ์ธ๋ ๊ท์น์ ํธ์งํ์ฌ MYSQL๊ณผ ์ํตํด์ผํ๋ port 3307์ ์ ์ด์ค๋ค. ๋ฐฉ๊ธ ๋ง๋ ๋ณด์๊ทธ๋ฃน์ ์ ํํด์ ๊ท์น์ ๋ง๋ค์ด์ฃผ๋ฉด ๋๋ค!
์ด์ ๋ง๋ค์ด๋ ๋ณด์๊ทธ๋ฃน์ ์๊น ๋ง๋ค์ด์ค rds ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ค์ ์ ์ฉ์์ผ์ฃผ์.
โ์์ โ ๋ฒํผ์ ๋๋ฅด๊ณ ์๋ก ์์ฑํ๋ ๋ณด์ ๊ทธ๋ฃน์ ์ถ๊ฐํด์ฃผ๋ฉด ๋๋ค.
์ด์ ๋ณด์๊ทธ๋ฃน๊น์ง ์ค์ ์ด ๋ RDS ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์์ฑํด์คฌ๊ธฐ ๋๋ฌธ์ EB๊น์ง ๋ง๋ค์ด์ฃผ๋ฉด ๋๋ค. ์ด EB์์ ์๋ก ์์ฑํ ๋ณด์๊ทธ๋ฃน์ ์ถ๊ฐํ์ฌ ์ ์ฉ์์ผ์ฃผ๊ณ EB์ RDS ์ํต์ ์ํด์ ํ๊ฒฝ๋ณ์๋ฅผ ์ค์ ํ๋ฉด ๋!
language: generic
sudo: required
services:
- docker
before_install:
- docker build -t kkkkmd/react-test-app -f ./frontend/Dockerfile.dev ./frontend
script:
- docker run -e CI=true kkkkmd/react-test-app npm test
after_success:
- docker build -t kkkkmd/docker-frontend ./frontend
- docker build -t kkkkmd/docker-backend ./backend
- docker build -t kkkkmd/docker-nginx ./nginx
- echo "$DOCKER_HUB_PASSWORD" | docker login -u "$DOCKER_HUB_ID" --password-stdin
- docker push kkkkmd/docker-frontend
- docker push kkkkmd/docker-backend
- docker push kkkkmd/docker-nginx
deploy:
provider: elasticbeanstalk
region: "us-west-2"
app: "docker-fullstack-app"
env: "DockerFullstackApp-env"
bucket_name: elasticbeanstalk-us-west-2-896153392792
bucket_path: "docker-fullstack-app"
on:
branch: master
access_key_id: $AWS_ACCESS_KEY
secret_access_key: $AWS_SECRET_ACCESS_KEY
์ด ๋ถ๋ถ์ด ์ถ๊ฐ๋ ๊ฒ
์ ๋ฒ์ ํ๋๊ฑฐ๋ ๊ฑฐ์ ๋๊ฐ์
deploy:
provider: elasticbeanstalk
region: "us-west-2"
app: "docker-fullstack-app"
env: "DockerFullstackApp-env"
bucket_name: elasticbeanstalk-us-west-2-896153392792
bucket_path: "docker-fullstack-app"
on:
branch: master
access_key_id: $AWS_ACCESS_KEY
secret_access_key: $AWS_SECRET_ACCESS_KEY
provider : ์ธ๋ถ ์๋น์ค ํ์ (s3, elasticbeanstalk, firebase ๋ฑ)region : ํ์ฌ ์ฌ์ฉํ๊ณ ์๋ AWS์ ์๋น์ค๊ฐ ์์นํ๊ณ ์๋ ๋ฌผ๋ฆฌ์ ์ฅ์app : ์์ฑ๋ ์ดํ๋ฆฌ์ผ์ด์
์ ์ด๋ฆenv : ํด๋น elasticbeanstalk์ ์ํ s3 ๋ฒ์ผ ์ด๋ฆbucket_path : ์ดํ๋ฆฌ์ผ์ด์
์ ์ด๋ฆ๊ณผ ๋์ผ์์ค ํ์ผ์ ์ ๋ฌํ๊ธฐ ์ํ ์ ๊ทผ ์๊ฑด
- ๊นํ๋ธ
- Travis CI์ ๋ก๊ทธ์ธํ๋ ๊ณผ์ ์์ ๊นํ๋ธ ๊ณ์ ์ ์ฐ๋ํจ์ผ๋ก์จ ์ธ์ฆ ์๋ฃ
- Travis CI
- AWS์์ ์ ๊ณตํ๋ ์ก์ธ์ค ํค์ ๋น๋ฐ ์ก์ธ์ค ํค๋ฅผ Travis CI ์ ์ค์ ํ์ผ์ ์์ฑํจ์ผ๋ก์จ ์ธ์ฆ
- AWS
์ธ์ฆ์ ์ํด์๋ API Key๊ฐ ํ์
- Secret, Access API Key ๋ฐ๋ ์์
- IAM USER ์์ฑ
- APIํค๋ฅผ Travis yml ํ์ผ์ ์ ์ด์ฃผ๊ธฐ
- Travis CI์์๋ ์๊น Docker Hub ID, PASSWORD ๋ฅผ More options์์ ์ค์ ํด์ค๋ค.