SOPT 34기 서버파트/Docker 스터디

[Docker] 컨테이너 애플리케이션 구성

softmoca__ 2024. 5. 4. 21:56
목차

클라우드 네이티브(Cloud Native) 애플리케이션

클라우드

- 다른 회사의 서버를 빌려서 운영

- 다른 회사가 모두에게 서버를 빌려줄 경우 : 퍼블릭 클라우드(Public Cloud)

- 다른 회사가 특정 조직에게만 서버를 빌려줄 경우: 프라이빗 클라우드(Private Cloud)

- 사용 요청 즉시 서버를 생성(Provisioning)

- 실제 사용한 시간 만큼만 비용 지불

 

현대 애플리케이션이 겪는 다양한 문제들을 클라우드 환경 구성을 통해 해결

1. 트래픽이 증가할 때 빠르게 대처할 수 있는가? (확장성, Scalability)

클라우드 환경에서는 서버 추가가 10분 내로 이루어진다.

온프레미스(기업이 직접 서버 구축)에서는 서버가 미리 준비되어 있지 않은 경우 새로운 서버를 증가하는데 오랜 시간이 소요된다.(주문, 배송, 설치 등)

 

2. 장애 발생 시 빠르게 복구할 수 있는가? (복원력, Resilience)

클라우드 환경에서는 백업 및 복구가 빠르게 이루어질 수 있다. (Disaster Recovery,복구에 사용되는 서버)

장애에 대응하기 위한 다양한 지역의 서버를 구축할 수 있다.

 

3. 운영 비용을 효율적으로 운영할 수 있는가?

사용한 만큼만 지불할 수 있기 때문에 운영 비용에 더 효율적이다.

 

클라우드가 저렴할 것 같지만 실제로 비효율적으로 사용해서 비용이 훨씬 비싸게 청구되는 경우도 많다.

전문 아키텍트가 서버 가용량을 적절하게 구성해야 되고 비용 최적화를 지속적으로 수행해야 한다.

그리고 단순히 해외 서버를 구성한다고 해서 재해복구나 해외 서비스가 바로 이루어지는 것도 아니다.

서버를 구성하는 것은 이런 모든 과정의 시작점에 불과하며 핵심은 클라우드가 아닌 애플리케이션에 있다.

 

클라우드 네이티브 애플리케이션 - 클라우드 환경을 더 잘 활용할 수 있는 애플리케이션 구조

1. MSA

트래픽 증가에 빠르게 대처하기 위해선 애플리케이션이 MSA 구조로 개발되어야 한다.

 

2. 컨테이너 (Container)

 컨테이너를 활용해 실행 환경에 종속되지 않는 동작이 보장되어야 한다.

즉, 클라우드를 사용해 서버를 여러곳에 운영할수 있어야 한다.

 

 

3. 상태비저장 (Stateless)

애플리케이션 서버는 상태를 가지지 않아야 한다.

상태를 가지지 않는 애플리케이션은 어디에나 즉시 배포될 수 있다.

 

 

4. DevOps 및 CI/CD

배포가 자동화되어야 하고 빠르게 릴리즈가 수행되어야 한다.

 

 

MSA 와 모놀리식

 

 

 

Leafy 애플리케이션 구성

- 아래와 같은 구조를 가진 서비스를 컨테이너로 동작을 하도록 실습을 진행.

 

 

 

 

 

공부에 앞서 제공 되어 있는 실습 애플리케이션을 실행 시켜 보자.

 

docker network create leafy-network
컨테이너들이 사용할 네트워크 정의
 
docker run -d --name leafy-postgres --network leafy-network devwikirepo/leafy-postgres:1.0.0

 

 leafy-network라는 네트워크에 연결 하며 devwikirepo/leafy-postgres:1.0.0 이미지를 기반으로 leafy-postgres라는 이름의 컨테이너를 데몬 모드에서 실행.

 

 
docker logs -f leafy-postgres

db가 잘 실행 됨을 확인.

 

 

docker run -d -p 8080:8080 -e DB_URL=leafy-postgres --network leafy-network --name leafy devwikirepo/leafy-backend:1.0.0

 - leafy-network라는 네트워크에 연결 하며 devwikirepo/leafy-backend:1.0.0  이미지를 기반으로 leafy라는 이름의 컨테이너를 데몬 모드에서 실행.

- 컨테이너 내부의 8080 포트를 호스트 시스템의 8080 포트에 매핑.
   즉, 호스트 시스템에서 8080 포트로 접근하면 컨테이너 내부의 웹 서버에 연결

- 이전에 생성한 leafy-postgres를 호스트로 사용하도록 환경 변수 설정(컨테이너로 세팅한 DB의 호스트 이름은 컨테이너 이름이다.)

백엔드 애플리케이션이 실행됨을 확인
 
 
docker run -d -p 80:80 --network leafy-network --name leafy-front devwikirepo/leafy-frontend:1.0.0
프론트엔드 애플리케이션이 잘 실행됨을 확인
 

이 Leafy 애플리케이션을 컴퓨터에 실행하는 과정에서 Node.js나 Java,  Postgre 같은 소프트웨어가 하나도 설치되어 있지 않은 상태에서도 컨테이너 가상화를 통해서 애플리케이션을 아주 빠르게 구성할 수 있었다.

 

명령어를 실행하고 이미지를 다운로드 받는 시간만 놓고 보면 빠르면 5분 안으로 애플리케이션 서버들을 구성할수 있다.

이렇게 컨테이널르 사용하면 소프트웨어를 실행하기 위해 필요한 것들을 실행하는 컴퓨터에 설치하지 않고도 애플리케이션을 구성할 수 있다.

 

 

 

PostgreSQL 컨테이너 구성

- 실제 postgreSQL의 프로젝트 디렉토리 구조와 코든느 위와 같다.

 

FROM postgres:13

Postgres는 Nginx처럼 이미지에 소프트웨어가 포함되어 있기 때문에 별도의 설정 없이 Postgres 이미지만 실행해도 데이터베이스를 사용할 수 있다.

 

COPY ./config/postgresql.conf /etc/postgresql/custom.conf

하지만 기본 이미지에는 아무 데이터도 없기 때문에 저희는 초기 데이터를 구성하는 SQL을 작성해서 Postgres 이미지에 전달할 것이다.

 왼쪽과 같은 설정 변수들을 사용해서 PostgreSQL이 실행되며 COPY 명령어로 해당 코드 파일을 컨테이너 내부의 /etc/postgresql/custom.conf 로 복사해서 옮긴다.

즉, postgresql.conf파일을 /etc/postgresql/postgresql.conf 로 복사, 기본 설정 파일을 덮어쓰기하여 새로운 설정 적용

 

COPY ./init/init.sql /docker-entrypoint-initdb.d/

위과 같은 sql문을 사용해서 초기 데이터를 세팅한다.

위 init.sql  파일(빌드컨텍스트)을 COPY 명령어로 해당 코드 파일을 컨테이너 내부의 /docker-entrypoint-initdb.d/로 복사해서 옮긴다. 그러면 Postgres이미지가 컨테이너로 실행될 때 자동으로 이 디렉토리에 있는 SQL 문을 실행해 준다.

즉, init.sql파일을 /docker-entrypoint-initdb.d/ 로 복사, /docker-entrypoint-initdb.d/에 있는 sql문은 컨테이너가 처음 실행 시 자동실행.

 

+Docker 이미지에는 Entrypoint Hook이라는 기능이 있어 컨테이너가 실행될 때 자동으로 실행되는 명령어 또는 스크립트를 정의 할 수 있다. docker-entrypoint-initdb.d 디렉토리는 특히 PostgreSQL 컨테이너에서 사용되는 Entrypoint Hook의 일부이다.

 

CMD ["postgres", "-c","config_file=/etc/postgresql/custom.conf"]
 컨테이너를 실행할 때의 Postgres를 실행시키기 위해 실행명령은 cmd에 Postgres로 지정.
"-c", 옵션을 통해서 config 파일을 etc에 Postgres SQL에 custom.conf 파일로 지정.

 

 

 

 

Dockerfile 빌드시 내부에서 어떤 과정으로 이미지가 구성되는지 실습

docker cp 컨테이너명:원본위치 복사위치
# 컨테이너->호스트머신으로 파일 복사

docker cp 원본위치 컨테이너명:복사위치
# 호스트머신->컨테이너로 파일 복사

 

docker run -d --name postgres -e POSTGRES_PASSWORD=password postgres:13
docker exec -it postgres bin/bash

postgresql13 버전의 이미지를 통해 postgresql 컨테이너 실행 후 컨테이너 내부의 파일 목록 확인 

 

현재는 docker-entrypoint-initdb.d 디렉토리에 아무런 내용이 없다.

 

docker cp ./config/postgresql.conf postgres:etc/postgresql/postgresql.conf

docker cp 명령을 사용해서 .config/postgressql.conf 파일을  컨테이너 내부의  etc/postgresql/custom.conf 파일로 복사

 

 

 

docker cp ./init/init.sql postgres:docker-entrypoint-initdb.d/

docker cp 명령을 사용해서 ../init/init.sql postgres 파일을  컨테이너 내부의  docker-entrypoint-initdb.d/ 파일로 복사

 

 

위와 같이 postgres컨테이너 내부에 복사한 파일들이 잘 저장되있음을 확인

 

psql -U postgres -c "\d"
psql -U postgres -f /docker-entrypoint-initdb.d/init.sql

 

psql: PostgreSQL 데이터베이스 클라이언트 명령어.

-U postgres: PostgreSQL 사용자 postgres로 로그인.

-c "\d": PostgreSQL 데이터베이스에 대한 정보를 출력

 

-f /docker-entrypoint-initdb.d/init.sql:  /docker-entrypoint-initdb.d/init.sql 파일의 내용을 PostgreSQL 데이터베이스에 실행

 

 

 

 

Dockerfile 빌드 실습 

docker build -t softmoca/leafy-postgres:1.0.0 . --no-cache

위 dockerfile을 사용해서 빌드.(이미지의 이름은 softmoca/leafy-postgres:1.0.0)

docker push softmoca/leafy-postgres:1.0.0

나의 계정으로 push

docker run -d --name leafy-postgres --network leafy-network softmoca/leafy-postgres:1.0.0

위에서 빌드한 이미지로 컨테이너를 실행

 

docker exec -it leafy-postgres su postgres bash -c "psql --username=myuser --dbname=mydb"

leafy-postgres 컨테이너 내부에서 postgres 사용자 권한으로 bash 쉘을 실행한 후, 해당 쉘에서 psql 명령어를 이용하여 myuser 사용자로 mydb 데이터베이스에 연결하는 작업을 수행.

 

mydb=# SELECT * FROM users;
mydb=# SELECT * FROM plants;
mydb=# SELECT * FROM user_plants;

위와 같은 명령어로 데이터들을 확인.

 

 

Postgres 이미지의 레이어 확인 

 

 

 

 

 

 

 

SpringBoot 백엔드 컨테이너 구성

${DB_URL}로 환경 변수를 불러 올수 있으며 해당 환경 변수가 없으면 : 뒤에 값이 디폴트 값으로 들어간다.

이전 postgres 컨테이너의 dockerfile에서 ENV 명령어로 설정한 것과 같다.

하지만 DB_URL의 경우 localhost가 아닌 실제 데이터베이스 서버의 URL인 leafy-postgres(컨테이너로 생성한 Postgres의 호스트url은 컨테이너 이름)로 수정해야 한다. 그래서 컨테이너를 실행(run) 할 때 환경변수를 주입한다.

 

 

도커 파일 빌드시 내부에서 어떤 과정으로 이미지가 구성되는지 실습

 

docker run -it --name gradle gradle:7.6.1-jdk17 bash
mkdir /app && cd /app

gradle:7.6.1-jdk17 이미지를 사용해서 gradle이라는 컨테이너 생성 후 해당 컨테이너 내부 shell로 접속.

WorkDIR 지시어를 사용했을떄 나타나는 효과를 위해 app디렉토리 생성 후 app으로 이동.

 

 

docker cp . gradle:app

컨테이너로 소스 코드들 복사 후 복사가 잘 된 것을 확인

 

 

gradle clean build -no-daemon

 

애플리케이션 빌드 후 build 디렉토리 및 jar 파일이 생성 됫것을 확인.

 

 

java –jar build/libs/Leafy-0.0.1-SNAPSHOT.jar

위 명령어로  애플리케이션을 실행 시킬수 있다.

하지만 DB의 URL 호스트를 수정해 주지 않아 에러가 나온다.

dockerfile로 빌드를 하며 다시 실행 시켜 보자.

 

Dockerfile 빌드 실습 

 

 

 

 

 

 

Vue.js 프론트엔드 컨테이너 구성

 

 

 

 

 

 

 

 

 

https://www.inflearn.com/course/lecture?courseSlug=%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%A5%BC-%EC%9C%84%ED%95%9C-%EC%89%AC%EC%9A%B4-%EB%8F%84%EC%BB%A4