1. 간단한 앱 배포(단일 컨테이너)
가. Dockerfile.dev vs Dockerfile
•
도커파일 작성 시, 개발환경과 배포환경을 구분하여 두 가지로 작성함
→ 개발환경과 배포환경에서 도커 파일의 내용이 달라짐
→ 개발환경에서는 Dockerfile.dev로 파일명 설정
→ 개발환경에서 빌드 시 f 옵션을 추가하여 빌드함
ex) docker build -f Dockerfile.dev ./
→ naming build: docker build -f Dockerfile.dev -t gentlemj/docker-react-app ./
•
Dockerfile.dev 내 RUN npm install 부분에서 이미 node_modules 부분이 컨테이너 HD에 설치 완료됨. 따라서 local에 있는 node_modules를 COPY ./ ./에 따라 컨테이너 HD에 추가적으로 복사될 필요가 없음. 심지어 node_modules는 용량이 크므로 시간이 오래걸림. 따라서 local 내 해당 폴더를 삭제하는 것이 효율적
나. 도커 이미지로 리액트 앱 실행
•
기본 실행 명령
→ docker run gentlemj/docker-react-app
•
네트워크 포트 맵핑 포함 명령
→ docker run -it -p 3000:3000 gentlemj/docker-react-app
→ 리액트 기본 포트는 3000이므로 위와 같이 설정
•
Volum 활용하여 실행(VSCode 내 bash 실행 X, Window cmd 활용할 것)
→ docker run -it -p 3000:3000 -v /usr/src/app/node_modules -v %cd%:/usr/src/app gentlemj/docker-react-app
•
Docker Compose로 간단하게 앱 실행
→ 아래와 같이 docker-compose 파일을 작성한 후, docker-compose up 명령어로 실행
→ context: docker file의 위치
image from John Ahn, https://www.inflearn.com/course/따라하며-배우는-도커-ci/dashboard
•
리액트 앱을 도커환경에서 테스트하기
→ docker run -it 이미지 이름 npm run test
→ 테스트 코드 추가하 위의 run 명령을 입력해도 테스트 케이스가 증가 X, 이를 해결하기 위해 compose 파일 작성
image from John Ahn, https://www.inflearn.com/course/따라하며-배우는-도커-ci/dashboard
→ docker-compose up —-build: 먼저 리액트 앱 실행 후 이 앱을 테스트함
다. 운영환경(배포 후)
•
Nginx 웹서버 필요성
→ 개발환경은 소스 변경시 자동으로 전체 앱을 빌드 후 변경사항 반영되야 함. 반면 배포환경은 오히려 소스 변경에 따라 앱에 자동 반영 필요 X, 이외에도 개발 환경에 적합한 기능이 개발서버에 특화
→ Nginx의 경우 운영에만 필수적인 기능으로 구성되어 빠르게 작동함
image from John Ahn, https://www.inflearn.com/course/따라하며-배우는-도커-ci/dashboard
image from John Ahn, https://www.inflearn.com/course/따라하며-배우는-도커-ci/dashboard
•
운영환경 Dockerfile 작성
→ 운영환경의 소스코드는 build 폴더 내 저장, 반면 개발환경의 소스 파일은 src나 public 폴더 내 저장
→ 운영환경 Dockerfile의 내부를 두 부분으로 나누어서 이해
1.
빌드 파일 생산(Builder Stage)
image from John Ahn, https://www.inflearn.com/course/따라하며-배우는-도커-ci/dashboard
1.
Ngnix 가동 및 빌드폴더 내 파일을 웹 브라우저의 요청에 따라 제공(Run Stage)
image from John Ahn, https://www.inflearn.com/course/따라하며-배우는-도커-ci/dashboard
•
배포 실행
→ 이미지 생성: docker build ./
→ 실행: docker run -p 8080:80 이미지 이름(또는 아이디)
참고) Ngnix 기본포트는 80
라. Travis CI
•
Travis CI(Continuous Intergration): Github repository에 올라온 프로젝트를 특정 이벤트에 따라 자동으로 테스트, 빌드, 배포 지원
•
Travis CI 흐름
image from John Ahn, https://www.inflearn.com/course/따라하며-배우는-도커-ci/dashboard
•
travis.yml 소스 구성
image from John Ahn, https://www.inflearn.com/course/따라하며-배우는-도커-ci/dashboard
→ befor_install 부분은 script 부분의 테스트 명령이 정상적으로 작동하기 위해 설정해야 할 부분임.(대표적인 예가 컨테이너 빌드)
→ CI=true, travis CI 환경에서 작동하기 위해 명시
→ — —coverage, 테스트 부분에 대한 상세 출력
→ App.test.js에서 테스트하는 것은 App.js의 learn react 부분 텍스트의 존재유무임. 따라서 이 부분을 제거하면 테스트 실패할 것
마. AWS 배포
•
Amazon EC2(Elastic Compute Cloud): AWS(Amazon Web Services)에서 제공하는 클라우드 확장식 컴퓨터
→ 클라우딩 시스템 안에 웹서비스를 위한 환경 구축 가능(웹서버, DB 등), 1대의 컴퓨팅 시스템을 EC2 인스턴스라 지칭
•
EB(Elastic BeanStalk): 웹앱 및 웹서비스를 배포하고 확장하는데 편리한 환경을 제공하는 서비스
→ EC2 인스턴스나 DB를 포함한 환경 제공하여 앱 업데이트마다 자동으로 환경관리
image from John Ahn, https://www.inflearn.com/course/따라하며-배우는-도커-ci/dashboard
•
EB 환경 구성
→ 로드 밸런서: 트래픽이 증가하면 EC2 인스턴스를 추가 생성하여 트래픽을 분산하는 기능
image from John Ahn, https://www.inflearn.com/course/따라하며-배우는-도커-ci/dashboard
•
.travis.yml 파일 작성(배포부분)
→ S3: 일종의 파일 저장소로, Travis CI의 파일을 압축해서 S3로 전송함
→ on, branch:master, master branch에 push가 될 때에만 배포 실행 명시
image from John Ahn, https://www.inflearn.com/course/따라하며-배우는-도커-ci/dashboard
image from John Ahn, https://www.inflearn.com/course/따라하며-배우는-도커-ci/dashboard
•
Travis CI의 AWS 접근을 위한 API 생성
→ 소스코드 이동
image from John Ahn, https://www.inflearn.com/course/따라하며-배우는-도커-ci/dashboard
•
Secret, Access API Key 받는 순서
→ IAM(Identity and Access Management): AWS 리소스에 대한 접근을 안전하게 제어하는 서비스
image from John Ahn, https://www.inflearn.com/course/따라하며-배우는-도커-ci/dashboard
→ Secret, Access Key는 노출이 되면 안되므로 Travis의 특정 저장소에 저장
•
port 설정
→ Dockerfile에 ngnix에 대한 포트맵핑을 추가함
→ EXPOSE 80
2. 복잡한 앱 배포(다중 컨테이너)
참고) Todo List 배포 절차를 참고할 것
가. 전체적인 흐름 이해
•
full-stack app(=== multi-container app)
image from John Ahn, https://www.inflearn.com/course/따라하며-배우는-도커-ci/dashboard
•
Proxy(Ngnix server) 활용 설계
image from John Ahn, https://www.inflearn.com/course/따라하며-배우는-도커-ci/dashboard
나. Node JS 구성
1.
package.json 만들기(npm init)
2.
package.json 내 스크립트와 종속성 명시
dependancies
3.
server.js 기본구조 작성
4.
db.js 작성하여 mysql 연결
•
host, user, password, db 명시하여 pool 생성 및 export
5.
server.js에서 db pool 가져오기
6.
API 작성
•
DB 값 받아서 Client에 전송 API
// server.js
app.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(results);
});
});
JavaScript
복사
•
Client에서 입력값 받아서 DB 내 저장 API
// server.js
app.post("/api/value", function (req, res, next) {
db.pool.query(
`INSERT INTO lists (value) 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 });
}
);
});
JavaScript
복사
•
(임시적)server.js 내 DB 테이블 생성
// server.js
db.pool.query(
`CREATE TABLE lists (
id INTEGER AUTO_INCREMENT,
value TEXT,
PRIMARY KEY (id)
)`,
(err, results, fileds) => {
console.log("results", results);
}
);
JavaScript
복사
다. Dockerfile(Node JS) 작성
•
간단하므로 생략
라. React JS 구성
1.
리액트 앱 생성
2.
App.js 내 UI 생성(input 및 Buttion 추가)
3.
CSS 추가
4.
State 관리
•
lists: DB 값 가져와서 저장 시 사용, 빈 배열 초기값으로 설정
•
value: Client input값 저장 시 사용, 빈 문자열 초기값으로 설정
5.
eventhandler 추가
•
submitHandler: 기존 lists 상태에 DB에서 가져온 데이터를 추가하고 value 값을 빈 문자열로 설정
•
changeHandler: input 값으로 value 값 업데이트
6.
JSX 부분
•
lists 상태가 빈 배열이 아닐 시, lists 내 모든 값을 li 태그에 따라 출력
마. Dockerfile(React JS) 작성
1.
→ 바로 위 챕터와 동일
2.
배포환경을 위한 Dockerfile 작성
•
정적 파일을 빌드하는 부분과 Ngnix에 정적 파일 요청 시 빌드한 파일을 제공하는 부분으로 구분
•
local에서 생성한 파일을 container 내로 copy
image from John Ahn, https://www.inflearn.com/course/따라하며-배우는-도커-ci/dashboard
•
정적 파일을 제공하는 부분의 세부사항은 default.conf로 명시
→ ngnix가 listen하는 포트 명시
→ location / 경로로 요청시 제공할 빌드 파일
image from John Ahn, https://www.inflearn.com/course/따라하며-배우는-도커-ci/dashboard
바. DB 구성 & Dockerfile
•
개발환경 도커 활용 DB 작업 vs 운영환경 AWS RDS 서비스 활용
→ DB 내 실제 데이터의 중요도를 감안하여 안정적으로 데이터 관리할 수 있는 서비스 활용
image from John Ahn, https://www.inflearn.com/course/따라하며-배우는-도커-ci/dashboard
image from John Ahn, https://www.inflearn.com/course/따라하며-배우는-도커-ci/dashboard
•
Docker 환경에 mysql 설치
사. Ngnix Dockerfile & Docker Compose
•
프록시 기능
image from John Ahn, https://www.inflearn.com/course/따라하며-배우는-도커-ci/dashboard
•
추후 작성할 docker-compose 파일의 설정과 연동되는 부분이 있음
→ backend도 마찬가지
image from John Ahn, https://www.inflearn.com/course/따라하며-배우는-도커-ci/dashboard
•
컨테이너들을 연결시키기 위해 Docker compose 작성
1.
docker-compose.yml 작성
2.
각각의 서비스를 위한 틀 작성(frontend, backend, nginx, mysql)
3.
frontend
→ ./frontend 내에서 도커파일 찾아서 빌드하고, volumes 사용하여 참조가 불필요한 파일 설정(node_modules) 및 참조할 폴더 및 워킹디렉토리(/app) 연결
4.
nginx
→ 재시작 정책
image from John Ahn, https://www.inflearn.com/course/따라하며-배우는-도커-ci/dashboard
5.
mysql
volumes 부분은 도커 컨테이너 외 호스트 파일 시스템(도커에 의해 통제되는 AREA 내 존재)에서 db 내용을 저장하기 위해 설정함
image from John Ahn, https://www.inflearn.com/course/따라하며-배우는-도커-ci/dashboard
아. 운영 환경으로 전환
◦
도커 내 MySQL 정리(AWS 환경에서 운영할 예정)
mysql 폴더 삭제 불필요. docker-compose에서 mysql 부분 제거
◦
Travis CI Steps
1.
깃헙에 push
2.
Travis CI에서 해당 코드 가져옴
3.
Travix CI에서 테스트 코드 실행
4.
테스트 성공 시 이미지 build
5.
빌드된 이미지를 Docker Hub 전송
6.
AWS EB에서 Docker Hub부터 이미지 받아와서 배포
◦
Travis yml 파일 작성
image from John Ahn, https://www.inflearn.com/course/따라하며-배우는-도커-ci/dashboard
image from John Ahn, https://www.inflearn.com/course/따라하며-배우는-도커-ci/dashboard
image from John Ahn, https://www.inflearn.com/course/따라하며-배우는-도커-ci/dashboard
◦
Dockerrun.aws.json 작성
→ Dockerfile이 여러개인 경우, EB가 처리 불가. EB가 Dcokerfile 처리할 때 임의의 설정을 위의 파일에 명시
image from John Ahn, https://www.inflearn.com/course/따라하며-배우는-도커-ci/dashboard
image from John Ahn, https://www.inflearn.com/course/따라하며-배우는-도커-ci/dashboard
image from John Ahn, https://www.inflearn.com/course/따라하며-배우는-도커-ci/dashboard
◦
다중 컨테이너 앱을 위한 EB 환경 설정
→ 이름 및 플랫폼 지정(Docker, Multi-container)
→ 위의 모든 설정 완료 후 '.travis.yml' push하면 배포 완료
Reference
•
코드 참고, todolist-app