(도커) 도커 실무
개발자를 위한 쉬운 도커 (데브위키)
레이어 관리
- Dockerfile에 작성된 지시어 1개당 레이어가 1개가 추가된다.
- 불필요한 레이어가 많아지면 이미지의 크기ㅣ가 늘어나 빌드 속도가 느려진다.
-
따라서, 명령어의 수를 줄여 레이어의 개수를 최소한으로 만들어야한다.
- 이와 같이 RUN 지시어는 &&를 활용하여 하나의 명령어 안에서 모든 명령문이 처리되도록 한다.
- 애플리케이션의 크기를 가능한 작게 관리하여 이미지의 크기를 작게 만들어야한다.
- alpine OS를 사용하여 베이스 이미지를 작은 이미지로 사용할 수 있다.
캐싱을 활용한 빌드
- Dockerfile에 작성된 순서대로 결과 이미지의 레이어가 쌓인다.
- Docker는 각 단계의 결과 레이어를 캐시 처리한다. 지시어가 변경되지 않는다면 다음 빌드에서 레이어를 재사용한다.
- COPY, ADD 명령의 경우 빌드 컨텍스트의 파일 내용이 변경되어도 캐시를 사용하지 않는다.
- 레이어가 변경되면 그 레이어와 이후의 모든 레이어는 캐시를 사용하지 않고 새로운 레이어가 만들어진다.
- 따라서, 잘 변경되지 않는 파일들을 아래 레이어에 배치하면, 더 많은 레이어에 캐시를 적용할 수 있다.
- package.json, package-lock.json파일은 외부 라이브러리 정보가 저장되어 있어 개발 시 자주 변경되지 않는다.
- 따라서, 거의 변경되지 않는 레이어와 함께 두어 캐시를 활용할 수 있도록 할 수 있다.
Tier 아키텍처 구성
- Nginx의 프록시 기술을 활용해 보안에 뛰어난 3Tier 아키텍처를 구성한다.
- Nginx는 특정 경로로 온 요청(/api로 시작하는 경로)를 지정한 서버로 전달된다.
- Nginx를 프록시 서버를 활용하여 보안 향상, 부하 관리 및 API 응답 캐싱을 활용할 수 있다.
- 클라이언트는 원하는 정보를 조회 및 저장하기 위해 웹서버에 접속한다.
- 웹서버는 요청 프록시를 WAS에 전달한다.
- WAS는 DB서버에서 데이터 저징 및 조회를 진행하고 결과 값을 반환받는다.
- WAS는 결과 값을 활용하여 데이터를 가공하여 웹서버에 결과 값을 응답해준다.
- 웹서버는 응답받은 데이터를 활용하여 동적화면을 구성하여 클라이언트에 결과를 전달한다. 만약, 클라리언트가 정적인 자료를 요청할 경우 웹서버는 결과 값을 바로 응답한다.
도커에서 Tier 아키텍처 구성하기
- /api로 시작하는 요청은 프론트엔드 컨테이너로 프록시 되도록 설정한다. 따라서, 백엔드 컨테이너에 Host OS의 80포트의 /api경로로 접근을 시도하면 프론트엔드 컨테이너를 거쳐 접근이 가능하다.
- Nginx서버에서 프록시 되어 있기 때문에 외부서버에선 프론트엔드 서버에만 접근이 가능하다.
- 데이터베이스 컨테이너는 포트포워딩 자체가 안되어있기 때문에 외부에서 접근이 불가능하다.
- 데이터베이스 컨테이너는 백엔드 컨테이너와 레코드를 통해 연결이 되어있기 때문에 백엔드 컨테이너를 통해서 접근이 가능하다.
동적 서버 설정
- Nginx서버에서 WAS 주소를 고정해서 설정해야한다.
- 그런데 환경 별로 Nginx가 프록시 해야하는 주소는 변할 수 있다.
- 그래서 프록시 설정의 주소를 바꾸기 위해선 이미지 빌드를 다시 해야한다.
- 이렇게 환경 별로 달라지는 프록시 해야하는 주소같은 정보는 시스템 환경 변수로 처리하면 컨테이너 실행시 결적할 수 있다.
- 이러한 설정을 동적 서버 설정이라 한다.
동적 서버 설정 방법
- 프론트엔드의 설정 파일을 수정하여 프록시 설정 주소를 변수로 지정하여 동적으로 값이 지정되도록 설정한다.
- Dockerfile을 수정하여 소스코드의 nginx.conf파일을 template 파일로 복사하고, 동적으로 지정될 기본 환경 변수를 지정한다.
PostgreSQL 이중화 DB 구성
- 만약, 단일 서버로 구성하면 하나의 서버에 장애 발생 시 전체 서비스의 장애로 이어지게된다.
- 하나의 서버에 장애가 발생하더라도 동일한 다른 서버가 동일한 역할을 수행할 수 있도록 고가용성을 보장하기 위해서 서버를 이중화하여 구성한다.
- 서버 이중화 DB를 구성하는 방법은 2가지이다.
- 첫번째는 여러 DB서버가 하나의 볼륨을 사용하는 방법이다. 이 구성은 간단하지만 볼륨의 문제가 발생할 경우 대처가 어렵다.
- 두번째는 여러 DB서버가 각각 하나씩의 볼륨을 사용하는 방법이다. 이 구성은 성능에 부하가 발생할 수 있고, 데이터의 싱크를 항상 맞추기 위해서 별도의 처리가 필요하다.
- 프라이머리-스탠바이 복제 구조
- 하나의 프라이머리 서버에서만 쓰기 작업이 수행되고, 스탠바이 서버는 읽기 전용으로 사용된다.
- 프라이머리 서버의 상태가 변경되었을 경우 스탠바이 서버에 상태를 복제한다.
- 읽기 전용 스탠바이 서버는 여러개의 서버로 사용가능하다.
- 프라이머리-프라이머리 복제 구조
- 모든 서버에 읽기/쓰기 작업이 수행된다.
- 여러 서버에서 동시에 쓰기 작업이 일어나 동기화 구성 작업이 매우 복잡하다.
프라이머리-스탠바이 이중화 DB 구성
- 프라이머리와 스탠바이 노드를 같은 방식으로 실행한다.
- 프라이머리 노트에는 테이블 생성 및 데이터 삽입과 같이 쓰기 작업을 수행하도록 한다.
- 스탠바이 노드에 프라이머리의 데이터가 동기화되어 있는지 확인한다.
컨테이너 내부에서 개발
일반 서버에서 개발할 때 문제점
- 개발자의 PC마다 설치된 언어 및 라이브러리 버전을 완전히 일치시키기 어려움
- 개발 환경과 배포 환경이 다를 경우 배포 시 장애 발생
- 새로운 개발자 합류 시 개발 환경 설버에 시간이 많이 필요하고, 개발 환경이 변화에도 많은 시간이 필요함
- 한명이 여러 프로젝트를 담당할 경우 각 프로젝트의 환경이 모두 달라야 하는 경우 프로젝트들이 한 번에 하나의 PC에서 관리되기 힘듦
도커 컨테이너 내부에서 개발
- 도커를 활용하면 같은 이미지를 활용하여 개발자의 PC들과 배포 서버의 환경을 완전히 일치시킬 수 있다.
- IDE의 원격 개발 환경 기능을 통해 각 컨테이너별로 격리된 개발 환경을 구성할 수 있다.
- 개발자의 PC에 프로젝트에 필요한 언어와 라이브러리의 설치가 필요가 없어 유지가 쉽다.
- json파일을 통해서 일관된 개발환경을 구성할 수 있다.
- forwardPosts로 오픈할 포트를 입력한다. 명령어 -p와 같은 역할을 한다.
- postCreateCommand로 개발환경에 필요한 라이브러리를 설치하는 명령어를 입력하여 실행하도록 한다.
- 다른 개발자와 같은 json 파일을 사용하여 개발환경을 일관되게 유지할 수 있다.
- 실제로 개발을 수행할 컨테이너를 정의하는 도커파일을 생성한다.
- FROM 지시어로 베이지 이미지로 노트 14버전을 사용한다.
- RUN 지시어로 운영체제의 패키지를 업데이트하고 필요한 유틸들을 설치한다.
- ARG 지시어를 사용하여 node라는 사용자에게 적절한 권한을 부여한다.
- ENV 지시어를 사용하여 개발용컨테이너라는 것을 명시한다.