Infra/Docker

[Docker] Docker Compose 사용해 web, db 컨테이너 연결하기 (springboot, mariadb) (2-tier 구조)

당닝 2021. 11. 17. 16:56
728x90
목차
1. Docker Compose 생성하기
2. Local에서 db의 데이터 띄우는 간단한 web 구현하기(SpringBoot + MariaDB)
3. jar 파일 만들기

4. Dockerfile 만들기
5. 실행시키기
6. db 컨테이너 초기 설정
7. web 컨테이너 실행시키기

 

 

 

만약 도커가 설치되어있지 않다면 다음 글을 참고해주세요.

[Docker] 도커 시작하기 - 1. 도커 설치하기 (tistory.com)

 

도커의 기본적인 명령어를 모른다면 다음 글을 참고해주세요.

[Docker] 도커 시작하기 - 2. 도커 기본 명령어 (tistory.com)

 

 

 

1. Docker Compose 생성하기

먼저, 원하는 위치에 프로젝트 폴더를 생성하고, docker-compose.yml 파일을 만든다.

 

version: '3'

services:
  db:
    image: mariadb
    environment:
      - MARIADB_ROOT_PASSWORD=ctdx2378@
    ports:
      - "3306:3306"

  web:
    build:
      context: .
      dockerfile: ./compose/springboot/Dockerfile
    ports:
      - "8080:8080"
    volumes:
      - ./:/app/

이후 VS Code 등을 이용해 파일을 열고, 다음 내용을 적어준다.

하나씩 알아보도록 하겠다.

 

version

version: '3'

파일 규격 버전이다. '3'만 적으면 3으로 시작하는 최신 버전을 사용한다는 의미이다.

 

services

services:

services 밑으로 실행하려는 컨테이너를 정의할 것이다.

 

DB 컨테이너

db

services:
  db:

컨테이너명을 db로 정했다.

 

image

services:
  db:
    image: mariadb

db 컨테이너에서 사용할 이미지이다. mariadb를 사용할 것이다.

 

environment

services:
  db:
    image: mariadb
    environment:
      - MARIADB_ROOT_PASSWORD=1234

docker run 명령어의 -e 옵션에 해당한다. 컨테이너 내의 환경변수를 설정하는 것이다.

MARIADB_ROOT_PASSWORD=비밀번호를 통해 mariadb의 비밀번호를 지정해준다.

 

ports

services:
  db:
    image: mariadb
    environment:
      - MARIADB_ROOT_PASSWORD=ctdx2378@
    ports:
      - "3306:3306"

build run의 -p 옵션에 해당한다. 호스트와 컨테이너의 포트를 3306으로 설정했다.

 

web 컨테이너

web

services:
  web:

컨테이너명을 web으로 정했다.

 

build

services:
  web:
    build:
      context: .
      dockerfile: ./compose/springboot/Dockerfile

docker build 명령어에 해당한다. (2번의 web 구현 시 더 자세히 설명하도록 하겠다.)

context는 build를 진행할 위치이며(jar 파일이 이곳에 위치해야 한다.), dockerfile은 Dockerfile의 위치이다.

 

ports

services:
  web:
    build:
      context: .
      dockerfile: ./compose/springboot/Dockerfile
    ports:
      - "8080:8080"

호스트와 컨테이너의 포트를 8080으로 설정했다.

 

 

 

2. Local에서 db의 데이터 띄우는 간단한 web 구현하기(SpringBoot)

Spring Initializr에서 다음과 같이 구성하고 GENERATE를 눌러 다운받는다.

 

springboot로 다음과 같이 구현하였다. 하나씩 살펴보도록 하겠다.

 

build.gradle

buildscript {
	repositories {
		mavenLocal()
		maven { url 'https://maven.aliyun.com/repository/google/' }
		maven { url 'https://maven.aliyun.com/repository/public/' }
		maven { url 'https://maven.aliyun.com/repository/spring/' }
		maven { url 'https://maven.aliyun.com/repository/gradle-plugin/' }
		maven { url 'https://maven.aliyun.com/repository/spring-plugin/' }
		maven {
			url "https://plugins.gradle.org/m2/"
		}
		mavenCentral()
	}
	dependencies {
		classpath("org.springframework.boot:spring-boot-gradle-plugin:2.5.6")
		classpath "io.spring.gradle:dependency-management-plugin:1.0.11.RELEASE"
	}
}

plugins {
	id 'java'
}

apply plugin: "org.springframework.boot"
apply plugin: "io.spring.dependency-management"

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-web'

	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
	implementation 'org.springframework.boot:spring-boot-starter-jdbc'
	implementation 'org.projectlombok:lombok:1.18.20'
	runtimeOnly 'org.mariadb.jdbc:mariadb-java-client:2.7.4'
	developmentOnly 'org.springframework.boot:spring-boot-devtools'

	compileOnly 'org.projectlombok:lombok:1.18.22'
	annotationProcessor 'org.projectlombok:lombok:1.18.22'

	testCompileOnly 'org.projectlombok:lombok:1.18.22'
	testAnnotationProcessor 'org.projectlombok:lombok:1.18.22'

	implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.1.2'

	testImplementation('org.springframework.boot:spring-boot-starter-test'){
		exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
	}
}

test {
	useJUnitPlatform()
}

 

application.properties

spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
spring.datasource.url=jdbc:mariadb://proj-db-1:3306/test
spring.datasource.username=root
spring.datasource.password=1234

#update the schema with the given values.
spring.jpa.hibernate.ddl-auto=update
#To beautify or pretty print the SQL
spring.jpa.properties.hibernate.format_sql=true
#show sql
spring.jpa.properties.hibernate.show-sql=true
#show parameter binding
logging.level.org.hibernate.type.descriptor.sql=DEBUG

logging.level.org.hibernate.SQL=DEBUG

datasource.url에서 jdbc:mariadb://proj-db-1:3306/test에 주의해야한다.

proj-db-1은 db컨테이너명이고(proj compose가 생성되면 컨테이너명이 proj-db-1로 생성된다.) 3306은 db컨테이너의 포트번호이다.

 

만약 proj-db-1 대신 localhost를 넣게 되면 java.sql.SQLNonTransientConnectionException: Could not connect to address=(host=localhost)(port=3306)(type=master) : Socket fail to connect to host:localhost, port:3306. Connection refused (Connection refused)

오류가 뜨므로 꼭 확인하자. (로컬에서 실행시킬 때는 localhost를 써야한다.)

 

외에 username은 root, password는 환경변수로 설정했던 비밀번호인 1234를 입력한다.

 

SampleController.java

package com.sample.Controller;

import com.sample.Mapper.SampleMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

//@Controller
@RestController
public class SampleController {
    @Autowired SampleMapper sampleMapper;

    @RequestMapping("/")
    public String sampleView() {
        System.out.println(sampleMapper.selectSampleData());
        return sampleMapper.selectSampleData();
    }
}

 

SampleMapper.java

package com.sample.Mapper;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

@Mapper
public interface SampleMapper {
    @Select("select disposable_string from disposable_table")
    String selectSampleData();
}

 

Begin2Application.java

package com.sample;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Begin2Application {
    public static void main(String[] args){
        SpringApplication.run(Begin2Application.class, args);
    }
}

 

 

 

3. jar 파일 만들기

jar 파일은 여러 개의 자바 클래스 파일과, 클래스들이 이용하는 관련 리소스(텍스트, 그림 등) 및 메타데이터를 하나의 파일로 모아서 자바 플랫폼에 응용 소프트웨어나 라이브러리를 배포하기 위한 소프트웨어 패키지 파일 포맷이다.

jar 파일은 실제로 zip 파일 포맷으로 이루어진 압축 파일로서, 파일 확장자는 .jar이다. 

 

작성한 코드를 통해 jar 파일을 생성할 것이다.

 

Gradle > Tasks > build > bootJar을 클릭한다.

 

프로젝트 폴더 > build > libs에 jar 파일이 생성되었다.

 

이 jar 파일을 아까 만들어둔 proj 폴더에 옮긴다.

 

 

 

4. Dockerfile 만들기

도커가 이해할 수 있는 dockerfile을 만들어야 한다. 

compose 파일에서 build 옵션에 정의해둔 경로인 ./compose/springboot에 Dockerfile을 생성한다.

 

FROM openjdk:11
ARG JAR_FILE=*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]

내용은 다음과 같이 적어준다.

 

  • FROM : Docker Base Image (기반이 되는 이미지, <이미지 이름>:<태그> 형식으로 설정, java8로 코드를 작성했다면 11대신 8로 넣어줘야 합니다.)
  • ARG : 컨테이너 내에서 사용할 수 있는 변수를 지정할 수 있다.
  • COPY : 위에 선언했던 JAR_FILE 변수를 컨테이너의 app.jar로 복사한다.
  • ENTRYPOINT : 컨테이너가 시작되었을 때 스크립트 실행

 

 

 

 

5. 실행시키기
docker-compose up -d

proj 폴더 내로 경로를 이동해 다음 명령어를 입력한다.

 

 - Network proj_default  Created
 - Container proj-web-1  Started
 - Container proj-db-1   Started

와 같이 뜬다.

 

Docker Desktop을 확인해보면 다음과 같이 proj compose가 생겼다.

근데, proj-web-1은 실행이 멈췄다.

 

spring.datasource.url=jdbc:mariadb://proj-db-1:3306/test 로 url을 설정해놨는데 아직 test database를 만들지 않았기 때문이다.

 

 

 

6. db 컨테이너 초기 설정
docker exec -it proj-db-1 /bin/bash

exec 명령어를 통해 컨테이너를 실행한다.

 

root@___________:/#

제대로 실행이 됐다면 다음과 같이 뜰 것이다.

 

root@___________:/# mysql --version
mysql  Ver 15.1 Distrib 10.6.5-MariaDB, for debian-linux-gnu (x86_64) using readline 5.2

mysql --version을 입력하면 다음과 같이 버전이 뜬다.

 

root@___________:/# mysql -u root -p
Enter password:
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 3
Server version: 10.6.5-MariaDB-1:10.6.5+maria~focal mariadb.org binary distribution

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

먼저, mysql -u root -p를 입력해 db에 접속하고 컨테이너를 생성하며 입력한 비밀번호를 통해 로그인한다.

 

create database test;
use test;

test 데이터베이스를 만들고 use test를 통해 test db에 접속한다.

 

다음으로는, DB 사용자를 추가할 것이다.

MariaDB [test]> CREATE USER '{사용자 이름}'@'%' IDENTIFIED BY '{비밀번호}';
Query OK, 0 rows affected (0.010 sec)

MariaDB [test]> GRANT ALL PRIVILEGES ON *.* TO 'user'@'%';
Query OK, 0 rows affected (0.002 sec)

MariaDB [test]> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.000 sec)

다음과 같이 모든 DB, 테이블에 접속 가능한 사용자를 만든다. 

 

다음은, web에 띄울 data를 가진 테이블을 만들 것이다.

create table disposable_table(
    disposable_string VARCHAR(32)
  , disposable_int INT(8)
);

create문 통해 테이블 생성한다.

 

insert into disposable_table values ("data in db", "1");

insert문을 통해 데이터를 삽입한다.

 

MariaDB [test]> select * from disposable_table;
+-------------------+----------------+
| disposable_string | disposable_int |
+-------------------+----------------+
| data in db        |              1 |
+-------------------+----------------+

select문을 통해 테이블이 잘 생성되었는지 확인한다.

 

 

 

7. web 컨테이너 실행시키기

docker desktop에서 proj-web-1의 START를 눌러 실행시켜보자.

 

실행시키고, localhost:8080에 접속하면 db와 연동이 잘 된것을 확인할 수 있다.

728x90