Docker 적응기

정현진·2023년 1월 2일
0

docker

목록 보기
3/3
post-thumbnail

Docker 설치 및 spring boot 실행

노션에서 벨로그로 옮긴 내용들이다!
원문 : docker study

프로젝트를 컨테이너에 올리는 방식을 공부하고 적용하고 싶어서 docker를 이용해 공부를 해보았다.

OS는 Mac m1을 사용하였다.

  1. 먼저, docker를 설치해준다.

Install Docker Desktop on Mac

나는 m1칩이여서 Mac with Apple chip 클릭

  1. dmg파일 실행

끌어다 놓으면 설치 완료

  1. docker bashboard

여기서 쉽게 실행되고 있는 container 리스트나 image들을 확인할 수 있다.

나는 이미 계정이 있기에 프로젝트 터미널에서

docker login이라는 명령어를 실행하여 로그인을 하면 자동으로 로그인이 되었다.

계정이 없다면 아래 링크를 통해서 가입해주기 >.0

가입해주고 repository도 생성을 해주어야한다.

Docker Hub Container Image Library | App Containerization

  1. spring boot application 생성

spring boot 로 docker를 실행해줄거니까 spring boot 프로젝트를 만든다.

우선 Application의 전체 파일 구성, 필요한 구성은 아래와 같다.

  • Member : Entity
  • MemberRepository : Member Entity 영속성을 관리
  • DockerController : Member Entity를 조회할 수 있도록하고, 접속이 되는지 확인하는 controller
  • application.yml : jpa, jdbc 를 설정
  • pom.xml : 필요한 dependency를 설정하는 곳

1) maven 설정

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.6</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.gmc</groupId>
    <artifactId>docker-test</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    <name>docker-test</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>11</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

위와 같이 의존성을 추가해줍니다.

원래 기존에 진행하던 프로젝트의 pom.xml을 그대로 가져와서 필요없는 것이 많길래 몇개를 제외시켰습니다.

2) yml 파일 설정

pring:
  config:
    activate:
      on-profile: test
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://db:3306/test?serverTimezone=Asia/Seoul&characterEncoding=UTF-8
    username: root
    password: 1234
    dbcp2:
      test-while-idle: true
  jpa:
    open-in-view: true
    generate-ddl: true
    hibernate:
      ddl-auto: update
      naming:
        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
      use-new-id-generator-mappings: true
    properties:
      hibernate:
        #        show_sql: true
        format_sql: true
  jackson:
    serialization:
      fail-on-empty-beans: false
  output:
    ansi:
      enabled: detect

server:
  port: 9000
  servlet:
    context-path: /
    encoding:
      charset: UTF-8
      enabled: true
      force: true
  error:
    include-message: always

중요하게 봐야하는 부분

url: jdbc:mysql://db:3306/test?serverTimezone=Asia/Seoul&characterEncoding=UTF-8

원래는 굵은 글씨체로 되어있는 부분에 localhost라던지 다른 도메인 주소를 넣는다.

하지만 우리는 docker mysql image를 사용할 것이기 때문에 docker mysql image container 이름을 사용해준다.

docker와 통신을 하기 위해서는 container 이름을 이용하여 통신을 해야한다. !

custom docker network를 만들게 되면, container 생성시 부여한 이름으로 network 통신이 가능하다.

3) Entity 생성

import lombok.*;
import javax.persistence.*;

@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
@Entity
@Table(name = "auth_user")
public class Member {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(nullable = false, name = "member_id")
    private Long memberId;

    @Column(name = "name")
    private String name;
}

4) repository 생성

import com.gmc.dockertest.entity.Member;
import org.springframework.data.jpa.repository.JpaRepository;

public interface MemberRepository extends JpaRepository<Member, Long> {
}

5) controller 생성

import com.gmc.dockertest.repository.MemberRepository;
import com.gmc.dockertest.entity.Member;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
public class DockerController {
    private final MemberRepository memberRepository;

    @RequestMapping("/hello")
    public String hello() {
        return "hello";
    }

    @GetMapping("/save")
    public void test() {
        Member m1 = Member.builder()
                .name("정현진")
                .build();
        memberRepository.save(m1);
    }

    @GetMapping("/get")
    public String getM1() {
        return memberRepository.findAll().toString();
    }
}
  1. Dockerfile 생성
FROM adoptopenjdk/openjdk11
ARGJAR_FILE=target/*.war
COPY ${JAR_FILE} app.war
ENTRYPOINT ["java","-jar","-Dspring.profiles.active=test","/app.war"]

java 11환경으로 실행시킬 것이고, target 경로에 있는 war파일을 app.war로 카피하여 실행시킨다.

profile를 설정하고 있지 않다면 -Dspring.profiles.active=test 이 옵션을 빼준다.

ARGJAR_FILE의 경로는 gradle일 때와 maven일 때 서로 다르다.

maven : target/*.war

gradle : /build/libs/*.war

  1. war 파일 생성

maven package 를 이용하여 war파일을 생성한다.

target폴더 밑에 war파일이 생성된 것을 볼 수 있다.

  1. Docker network 생성

컨테이너간 통신을 컨테이너의 이름으로 하기 위해서는, custom network를 생성하고, 해당 network에 container를 생성해야한다.

docker create network test

test 라는 network를 생성한다.

참고자료
Docker - Docker Network란? (Docker Netowkr 사용예제)

  1. Docker image 생성
docker build -t [docker hub 아이디]/[docker hub repository 이름] --platform linux/amd64 .

뒤에 . 까지 꼭 ! 붙여줘야하며

mac m1 은 build시 --platform linux/amd64 문장을 넣어줘야 한다고 한다.

참고자료
https://github.com/JuHyun419/TIL-TodayILearned/issues/180

  1. docker push
docker push [docker hub 아이디]/[docker hub repository 이름]
  1. docker mysql container 생성
docker run --platform linux/amd64 -p 3306:3306 --name db -e MYSQL_ROOT_PASSWORD=1234 
-e MYSQL_DATABASE=test -e MYSQL_PASSWORD=1234 -d --network test mysql

위 명령어를 이용해 mysql container를 우선 실행합니다. 원래는 이미지를 다운 받아야 하지만, 해당 이미지가 도커 호스트에 존재하지 않는경우, Docker가 자동으로 docker hub에서 찾고 존재한다면, 다운을 받아줍니다.

  • -d : 백그라운드에서 container가 실행되도록 합니다.
  • -e: container 생성시 기본적으로 넘겨줄 파라미터를 지정합니다. 해당 mysql 이미지는 container 실행시, database root 관리자 비밀번호를 받도록 되어있습니다. Spring Boot Application을 생성할 때 Database 연결을 위해 지정한 비밀번호를 입력합니다.(1234)
  • -p: container가 외부에 노출할 port와 이 port에 연결하기 위해 docker host에서 사용할 port를 지정합니다.
  • --network: 우리가 생성한 custom network를 입력합니다.
  • --name: container에서 통신하기위해 사용할 이름을 부여합니다. Spring Boot Application을 생성할때 Database 연결을 위해 지정한 host 이름을 입력합니다. (db)

참고자료
참고자료

  1. mysql 실행
docker exec -it db bash

exec 명령을 이용해, db container에 연결함과 동시에 bash 셸을 실행 시킵니다.

user와 database가 있는 것을 확인하였다.

  1. spring boot 실행
docker run -it --name app --network test -p 9000:9000 [docker hub 아이디]/[docker hub repository 이름]
bash

--network
옵션을 이용해 mysql container와 같은 network에 container를 실행시키며, Spring Boot application 생성시 application.yml에서 지정한 port를 외부로 노출합니다.

  1. 최종 확인

1) /hello 경로 확인

2) /save 경로 실행

3) /get 경로 확인

4) docker ps

  1. 코드 수정 후 재실행

0) war package

1) image build

2) docker push

3) docker run

ERROR

  1. DB 연결이 막히는 상황

docker mysql container로 실행시켰을 때 말고

로컬에서 테스트를 진행 중 다른 외부 서버 접속 비허용을 한 host로 접속을 했을 때와 똑같은 오류가 났다.

이때 들었던 생각으로는 외부 접속이 막혔다는 것은 프로젝트 컨테이너 실행과 데이터베이스 컨테이너 실행이 각각 다른 network에서 실행되고 있는 것이 아닐까 생각을 하였다.

하지만 나는 test라는 이름을 가진 network로 실행을 시켰던 것 같아서

다시 앞에서 실행했던 코드를 찬찬히 살펴보니 ..

여기서 network 설정을 안해주었던 것이다..!

그래서 mysql 컨테이너를 삭제후 다시 network 설정을 하여 실행했더니

잘 실행되었다.

휴 ~..

전체적인 참고 사이트 (생명의 은인들)
Docker - Spring Boot Application Docker로 배포하기 및 Mysql 연동
[Docker] 스프링부트를 docker 이미지를 통해서 AWS EC2에 배포하기(DockerHub)

0개의 댓글