diff --git a/README.md b/README.md index 9bd7e429..218877eb 100644 --- a/README.md +++ b/README.md @@ -435,3 +435,89 @@ JWT를 통해 인증하는 과정은 다음과 같은 순서로 정리할 수 ## 후기 스프링 시큐리티에는 정말 많은 필터와 구현되어 있는 기능이 많고, 이를 이해하는 것이 시간적으로 조금 부족했다. 처음에는 개발된 코드를 그대로 사용하는 것부터 시작해야지 바로 커스텀해서 적용하는 건 정말 바보같은 행동(삽질하는 과정)이라는 것을 깨달았다. 그래도 좋았던 점은 디버깅 실력 +1 했다는 점! 정말 재밌었습니다. + +# 5주차 - Docker + +## 도커 컨테이너와 도커 이미지 + +### 도커를 사용하는 이유 + +도커는 리눅스의 응용 프로그램을 프로세스 격리 기술들을 사용해 컨테이너로 실행하고 관리하는 오픈 소스 프로젝트이다. 리눅스 컨테이너는 이런 프로세스 격리 방식만으로 OS 가상화의 효과를 누리면서, 아주 가볍고 바른 동작을 얻어낼 수 있다. 즉, CPU나 메모리를 딱 프로세스가 필요한 만큼만 추가가 가능하고, 성능적인 손실도 최소화 할 수 있다. + +도커를 이용해 프로그램을 설치하면 예상치 못한 에러도 덜 발생하며, 설치하는 과정도 훨씬 간단하다. + +### 도커의 정의 + +> 도커는 애플리케이션을 신속하게 구축, 테스트 및 배포할 수 있는 소프트웨어 플랫폼이다. 도커는 소프트웨어 컨테이너라는 표준화된 유닛으로 패키징하며, 이 컨테이너에는 라이브러리, 시스템 도구, 코드, 런타임 등 소프트웨어를 실행하는 데 필요한 모든 것이 포함되어 있다. 도커를 사용하면 환경에 구애받지 않고 애플리케이션을 신속하게 배포 및 확장할 수 있으며 코드가 문제없이 실행될 것임을 확신할 수 있다. + +### What is Container? + +> 도커 컨테이너는 코드와 모든 종속성을 패키지화하여 응용 프로그램이 한 컴퓨팅 환경에서 다른 컴퓨팅 환경으로 빠르고 안정적으로 실행되도록 하는 소프트웨어의 표준 단위다. + +컨테이너는 다양한 프로그램과 실행 환경을 컨테이너에 담고, 동일한 인터페이스를 제공하여 프로그램의 배포 및 관리를 단순하게 하는 기능을 한다. 즉 프로그램을 손쉽게 배포 및 관리할 수 있는 역할을 한다. + +도커 컨테이너를 만들기 위해서는 도커 이미지가 필요하다. 따라서 도커 컨테이너를 이해하려면 도커 이미지를 알아야 한다. + +### What is Docker Image? + +> 도커 이미지는 코드, 런타임, 시스템 도구, 시스템 라이브러리 및 설정과 같은 응용 프로그램을 실행하는 데 필요한 모든 것을 포함하는 가볍고 독립적이며 실행 가능한 소프트웨어 패키지다. + +아래의 도표를 살펴보면 이해하기 쉬워진다. + +![image](https://github.com/YoungGyo-00/TIL/assets/89639470/46580ba6-1b9b-48c6-bc9b-de16a41f981e) + +**도커 컨테이너 = 도커 이미지 인스턴스**이다. 하나의 도커 이미지로 여러 개의 도커 컨테이너를 만들어낼 수 있다. + +도커 컨테이너는 도커 이미지로 만들기 때문에 도커 미지 안에는 응용 프로그램을 실행하는 데 필요한 모든 설정과 종속성이 필요하다. + +도커 컨테이너는 도커 이미지를 실행한 상태라고 볼 수 있는데, 그래서 컨테이너에서 추가되거나 변하는 값은 이미지가 아닌 컨테이너 자체에 저장이 된다. 한마디로 컨테이너의 상태가 바뀌거나 삭제되더라도 이미지에는 영향을 미치지 않는다는 특징을 가지고 있다. + +### 도커를 사용할 때의 흐름 + +도커를 사용하는 흐름은 다음과 같습니다. + +1. 도커 클라이언트(CLI)에 원하는 명령을 위한 명령어 입력 +2. 도커 서버(도커 데몬)가 도커 클라이언트에 입력한 명령어를 전달받으면 이미지를 생성하고, 컨테이너를 실행 → 해당 컨테이너에서 애플리케이션 실행 + +도커 내부에서 어떤 일이 일어나는지 프로그램을 실행시킨 결과는 다음과 같습니다. + +![image](https://github.com/YoungGyo-00/TIL/assets/89639470/a3eaefc0-0e9b-42e2-950b-f11e39cd608c) + +hello-world 프로그램 내부적인 처리 과정 + +### 초기 과정(이미지가 로컬에 없는 경우) + +1. 도커 클라이언트에 명령어를 입력하면 클라이언트에서 도커 서버로 요청 +2. 서버에서 이미지가 로컬에 이미 다운로드된 적이 있는지 확인 +3. 기존에 내려받은 이미지가 없다면, ‘Unable to find image ‘hello-world:latest’ locally’ 문구 +4. 도커 이미지가 저장된 도커(Docker Hub)에서 이미지 가져오고 로컬에 보관 +5. 이미지를 이용해서 컨테이너 생성 +6. 생성된 컨테이너는 이미지에서 받은 설정이나 조건에 따라 프로그램 실행 + +### 도커 컨테이너의 생명주기 + +컨테이너의 생명 주기는 생성, 시작, 실행, 중지, 삭제 총 5단계로 구성되어 있다. + +모든 컨테이너는 이미지로부터 시작된다. 먼저 이미지를 통해 컨테이너를 생성(create)하고, 생성한 도커 컨테이너를 시작(start)해서 실행(running) 단계로 넘어간다. 컨테이너를 잠시 멈춘 상태는 중지(stop)할 수 있으며, 아예 사용하지 않는다고 생각되면 삭제(delete)를 할 수 있다. + +아래 이미지는 컨테이너의 생명 주기를 표현한 다이어그램이다. + +![image](https://github.com/YoungGyo-00/TIL/assets/89639470/dca615ac-c615-4e75-9510-ec44125e6052) + +### 이번 주차에 겪었던 사건 + +![스크린샷 2023-11-18 오후 10 05 24](https://github.com/YoungGyo-00/springboot-boilerplate/assets/89639470/5596e0b4-8acf-45da-af0f-1aec4e2744de) + +도커를 연결하며 겪었던 일은 로컬 데이터베이스와 도커 이미지 내 데이터베이스에서 있었다. jar 파일을 생성하고, 도커를 통해 서버를 띄우게 되면 데이터베이스와의 연결이 항상 문제가 있었다. `Dockerfile`을 통해 local DB에 접근하기 위해서 해결한 방법은 다음과 같다. + +``` +$ docker run -p 8080:8080 -e SPRING_DATASOURCE_URL=jdbc:mysql://host.docker.internal:3306/ceos18 -e SPRING_DATASOURCE_USERNAME=root -e SPRING_DATASOURCE_PASSWORD=비밀번호 market +``` + +docker-compose를 작동시킬 때는 도커 이미지 내의 mysql에 접근하는 과정에서 동일한 포트(3306)은 이미 사용 중이라고 표시가 되었다. 이때는 로컬에 있는 디비를 중지시키고 연결했다. 추가로, application.yml 파일의 데이터베이스 위치를 도커 이미지의 이름으로 변경하여 도커 이미지로 연결을 시켜주면서 해결했다. + +image + +### 소감 + +도커를 통해 처음으로 웹 애플리케이션을 띄워봤는데, 자동으로 이미지를 다운로드 받고 컨테이너를 만들어서 배포해주는 과정이 편리하다는 것을 이해할 수 있었다. 물론 중간에 서버를 개발할 때 만났던 오류와 다른 디비 연결 문제를 겪어서 해결하는 과정이 익숙하지 않아서 힘들었지만 환경에 구애받지 않고 모든 곳에서 사용할 수 있다는 것이 좋은 것 같다. diff --git a/market/Dockerfile b/market/Dockerfile new file mode 100644 index 00000000..f7975751 --- /dev/null +++ b/market/Dockerfile @@ -0,0 +1,4 @@ +FROM openjdk:17 +ARG JAR_FILE=/build/libs/*.jar +COPY ${JAR_FILE} app.jar +ENTRYPOINT ["java", "-jar", "/app.jar"] \ No newline at end of file diff --git a/market/docker-compose.yml b/market/docker-compose.yml new file mode 100644 index 00000000..7c70f286 --- /dev/null +++ b/market/docker-compose.yml @@ -0,0 +1,31 @@ +version: "3" + +services: + db: + container_name: db + image: mysql:latest + environment: + MYSQL_ROOT_PASSWORD: 12345678 + MYSQL_DATABASE: ceos18 + volumes: + - dbdata:/var/lib/mysql + ports: + - "3306:3306" + restart: always + + web: + container_name: web + build: . + ports: + - "8080:8080" + depends_on: + - db + environment: + mysql_host: db + restart: always + volumes: + - .:/app + +volumes: + app: + dbdata: \ No newline at end of file diff --git a/market/src/main/resources/application.yml b/market/src/main/resources/application.yml index 1666f7d3..b0bcb60f 100644 --- a/market/src/main/resources/application.yml +++ b/market/src/main/resources/application.yml @@ -3,14 +3,14 @@ spring: import: env.yml datasource: driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://localhost:3306/ceos18 + url: jdbc:mysql://db:3306/ceos18 username: root password: 12345678 jpa: database: mysql database-platform: org.hibernate.dialect.MySQL8Dialect hibernate: - ddl-auto: none + ddl-auto: create properties: hibernate: dialect: org.hibernate.dialect.MySQL8Dialect