Spring boot와 Docker Postgresql

Spring boot와 Docker Postgresql

이번엔 docker와 posrgresql에 대해 알아보겠다.
1. centos 6에 docker를 설치해보자
2. Spring boot와 Docker
3. Spring boot와 Docker Mysql

mysql과 소스는 동일하다.

@SpringBootApplication
public class SpringBootDockerPostgresqlApplication {

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

    @Autowired
    private AccountRepository repository;

    @Bean
    CommandLineRunner runner() {
        return args -> Arrays.asList(
                new Account(1L,"wonwoo","wonwoo@test.com"),
                new Account(2L,"kevin","kevin@test.com"),
                new Account(3L,"mink","mink@test.com")
        ).forEach(repository::save);
    }
}

Account class

@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Account {

    @Id
    @GeneratedValue
    private Long id;

    private String username;

    private String email;

}

AccountController class

@Slf4j
@RestController
public class AccountController {

    @Autowired
    private AccountRepository repository;

    @RequestMapping(value = "/accounts", method = RequestMethod.GET)
    public ResponseEntity<?> getAccount() {
        List<Account> accounts = repository.findAll();
        log.debug("accounts : {} ", accounts);
        return new ResponseEntity<>(accounts, HttpStatus.OK);
    }
}

AccountRepository class

@Repository
public interface AccountRepository extends JpaRepository<Account, Long> {
}

따로 설명은 하지 않겠다.
mysql과 다른점은 yml 파일과 maven이다.

application.yml

spring:
  jpa:
    hibernate:
      ddl-auto: create
    database-platform: org.hibernate.dialect.PostgreSQLDialect
  datasource:
    url: jdbc:postgresql://${POSTGRES_PORT_5432_TCP_ADDR}:${POSTGRES_PORT_5432_TCP_PORT}/docker
    username: dbuser
    password: dbpassword
    driver-class-name: org.postgresql.Driver

<dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <version>9.4-1200-jdbc4</version>
</dependency>

일단 postgresq pull 하자

docker run --name spring-boot-postgres -e POSTGRES_PASSWORD=dbpassword -e POSTGRES_DB=docker -d postgres

latest: Pulling from postgres
00b8e8227087: Pull complete 
1ad190f65f04: Pull complete 
60f2f5fb5bf9: Pull complete 
2d0c73368a74: Pull complete 
a786535117f1: Pull complete 
dd182ad340e4: Pull complete 
c05a4dbabb61: Pull complete 
d147dcf8581e: Pull complete 
358e57fb3884: Pull complete 
9c4b8b3535ba: Pull complete 
adf658a6b808: Extracting [==================================================>] 41.23 MB/41.23 MB
0fc677feeba3: Download complete 
0dceace87c23: Download complete 
23b5786d3dce: Download complete 
9b00a7295803: Download complete 
f88f356d246d: Download complete 
d6fb5e6e70f6: Download complete 
07e6c1333fa3: Download complete 
6f960967c8bf: Download complete 
d8bd0657b25f: Already exists 
a582cd499e0f: Already exists 

위와 같이 이미지를 생성한다.

docker images

이미지가 잘 있나 보자

postgres                    latest              6f960967c8bf        5 days ago          264.5 MB

잘있다.

다음으로 메이븐 빌드를 하자!

mvn clean package docker:build

빌드가 잘 되었다면

docker를 실행시키자

docker run --name spring-boot-docker-postgresql --link spring-boot-postgres:postgres -p 9000:8080 -d wonwoo/spring-boot-docker-postgresql

로그를 확인하기 위해 아래와 같이 입력하자

docker logs $CONTAINER_ID 

잘되었다면 브라우저를 열어 확인해보자
http://localhost:8080/accounts

그리고 postgres 클라이언트 연결도 가능하다.

docker run -it --link spring-boot-postgres:postgres --rm postgres sh -c 'exec psql -h "$POSTGRES_PORT_5432_TCP_ADDR" -p "$POSTGRES_PORT_5432_TCP_PORT" -U postgres'

위와 같이하면 접속도 가능하다.

postgres=# \l

                                 List of databases
   Name    |  Owner   | Encoding |  Collate   |   Ctype    |   Access privileges   
-----------+----------+----------+------------+------------+-----------------------
 docker    | postgres | UTF8     | en_US.utf8 | en_US.utf8 | 
 postgres  | postgres | UTF8     | en_US.utf8 | en_US.utf8 | 
 template0 | postgres | UTF8     | en_US.utf8 | en_US.utf8 | =c/postgres          +
           |          |          |            |            | postgres=CTc/postgres
 template1 | postgres | UTF8     | en_US.utf8 | en_US.utf8 | =c/postgres          +
           |          |          |            |            | postgres=CTc/postgres
(4 rows)

디비 목록이다.

postgres=# \connect docker

선택을 해보자

docker=# \d

테이블을 보자. account 테이블이 잘 있다.

                 List of relations
 Schema |        Name        |   Type   |  Owner   
--------+--------------------+----------+----------
 public | account            | table    | postgres
 public | hibernate_sequence | sequence | postgres
(2 rows)

한번씩 해보자!

Spring boot와 Docker Mysql

Spring boot와 Docker Mysql

  1. centos 6에 docker를 설치해보자
  2. Spring boot와 Docker

이번엔 도커에 mysql을 연동해보자.
연동이 되는지 확인해보기 위해 몇개의 클래스를 생성하자
간단하게 만들자

@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Account {

    @Id
    @GeneratedValue
    private Long id;

    private String username;

    private String email;

}

Account 엔티티 클래스다.

@Slf4j
@RestController
public class AccountController {

    @Autowired
    private AccountRepository repository;

    @RequestMapping(value = "/accounts", method = RequestMethod.GET)
    public ResponseEntity<?> getAccount() {
        List<Account> accounts = repository.findAll();
        log.debug("accounts : {} ", accounts);
        return new ResponseEntity<>(accounts, HttpStatus.OK);
    }
}

controller 클래스도 한개 만들자.
마지막으로 레파지토리도 생성하자.

@Repository
public interface AccountRepository extends JpaRepository<Account, Long> {
}

그리고 메이븐에 mysql connector를 추가해야된다.

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

그리고 yml 파일에 아래와 같이 추가하자

spring:
  jpa:
    hibernate:
      ddl-auto: create
    database-platform: org.hibernate.dialect.MySQLDialect
  datasource:
    url: jdbc:mysql://${MYSQL_PORT_3306_TCP_ADDR}:${MYSQL_PORT_3306_TCP_PORT}/${MYSQL_ENV_MYSQL_DATABASE}
    username: ${MYSQL_ENV_MYSQL_USER}
    password: ${MYSQL_ENV_MYSQL_PASSWORD}
    driver-class-name: com.mysql.jdbc.Driver
    validation-query: select 1

마지막으로 테스트 데이터를 넣자 Main 클래스에 넣자

@Autowired
private AccountRepository repository;

@Bean
CommandLineRunner runner() {
    return args -> Arrays.asList(
            new Account(1L,"wonwoo","wonwoo@test.com"),
            new Account(2L,"kevin","kevin@test.com")
    ).forEach(repository::save);
}

일단 설정은 끝났다.
그담 할일은 mysql을 pull 해오자.

docker run -d --name spring-boot-mysql -e MYSQL_ROOT_PASSWORD=password -e MYSQL_DATABASE=docker -e MYSQL_USER=dbuser -e MYSQL_PASSWORD=dbpassword -d mysql:latest

mysql dockerhub 참고

그리고 이미지가 존재 하는지 확인해보자.

docker images

java                        8                   31e7de89e3f8        5 days ago          642.3 MB
mysql/mysql-server          latest              26d67fdd58d2        4 weeks ago         294.8 MB
hello-world                 latest              975b84d108f1        4 months ago        960 B

이런식으로 나올거다.
그럼 잘된거다.
그런 다음에 다시 빌드를 하자.

mvn clean package docker:build

이상하게 첨엔 잘안되더니 docker를 재시작하니 또 된다.
이상하다. 리눅스가 클라우드서버라 약간 이상한듯 싶기도 하고 커널 버전도 안올라가 있어서..영 찜찜…아무튼
만약 빌드가 잘 안된다며 이것저것 다 해봐야댄다. 리부팅도 하고 막 암튼..

이제 spring boot를 실행해 보자.
spring이랑 mysql이랑 link를 걸어줘야된다.

docker run --name spring-boot-docker --link spring-boot-mysql:mysql -p 9000:8080 -d wonwoo/spring-boot-docker

요런식의 형태다.아래와 같이 하면 된다.
name은 컨테이너 명 아무거나 넣으면 댄다.
link는 저기 mysql container 명이다.

docker run --name app-container-name --link my-container-name:mysql -d app-that-uses-mysql

근데 필자는 No route to host이라는 에러가 자꾸 떳다.
찾아보니까

iptables -t filter -A DOCKER -d 172.17.0.0/16 -i docker0 -j ACCEPT

이렇게 하니까 된다.
원래 도커가 iptables을 건드는것도 같은데…아닌가?
아무튼 일단 된다.

필자의 처음으로 만든 dockerhub다

docker pull wonwoo/spring-boot-docker

참고

docker inspect $CONTAINER_ID  | grep IPAddress #컨테이너 아이피를 알아내는거다.
docker push $user-name/$app-container-name #도커 hub에 푸시

Spring boot와 Docker

spring boot와 Docker

일단 도커를 설치하자
설치 방법은 설치 리눅스(centos6.5) 기준이다.
일단 Spring boot 프로젝트를 만들자.
만드는법은 Spring boot 빠르게 시작해보자
혹은 Github example

@SpringBootApplication
@RestController
public class SpringBootDockerApplication {

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

    @RequestMapping("/")
    public String hello(){
        return "Hello Spring boot docker!";
    }
}

메인 소스다. 간단하게 만들었다.
그리고 추가 할 부분은
src/main/dockerDockerfile 파일을 만든다.

FROM java:8
VOLUME /tmp
ADD spring-boot-docker-0.0.1-SNAPSHOT.jar app.jar
RUN bash -c 'touch /app.jar'
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

추가하자.
다음은 maven 플러그인을 설정하자

<properties>
    <docker.image.prefix>wonwoo</docker.image.prefix>
</properties>

...


<plugin>
    <groupId>com.spotify</groupId>
    <artifactId>docker-maven-plugin</artifactId>
    <version>0.2.3</version>
    <configuration>
        <imageName>${docker.image.prefix}/${project.artifactId}</imageName>
        <dockerDirectory>src/main/docker</dockerDirectory>
        <resources>
            <resource>
                <targetPath>/</targetPath>
                <directory>${project.build.directory}</directory>
                <include>${project.build.finalName}.jar</include>
            </resource>
        </resources>
    </configuration>
</plugin>

그런다음에 빌드를하자
메이븐 기준이라…

mvn package && java -jar target/spring-boot-docker-0.0.1-SNAPSHOT.jar
#필자는 클라우드서버라 포트를 변경해야되서..
#mvn package && java -Dserver.port=9000 -jar target/spring-boot-docker-0.0.1-SNAPSHOT.jar 

웹브라우저를 열고 확인하자!
Hello Spring boot docker!
정상적으로 되는걸 확인했으니 이제 도커를 빌드하자.

mvn package docker:build

그럼 아래와 같은 화면이 나올 것이다.
이미지를 생성하는듯하다. 자바도 pull하는듯 하다. 흠

....

[INFO] Building image wonwoo/spring-boot-docker
Step 0 : FROM java:8
Pulling from java
d8bd0657b25f: Extracting [======================>                            ] 23.07 MB/51.37 MB
a582cd499e0f: Download complete 
3c3e582d88fa: Download complete 
5901462573ab: Download complete 
87d3bfd91a40: Download complete 
337c6b2193cb: Download complete 
c9f473494918: Download complete 
6d2585cde477: Download complete 
c49cfc438d8b: Download complete 
1d7d8f54c2b3: Download complete 
5f59c75f3075: Download complete 
7de249ebc2b5: Download complete 
7e810ba21977: Downloading [===================>                               ] 51.89 MB/129.9 MB
31e7de89e3f8: Download complete 

Status: Downloaded newer image for java:8
---> 31e7de89e3f8
Step 1 : VOLUME /tmp
---> Running in 22eb30aaef5d
---> 92198c129da9
Removing intermediate container 22eb30aaef5d
Step 2 : ADD spring-boot-docker-0.0.1-SNAPSHOT.jar app.jar
---> addd5f953ba5
Removing intermediate container a4fea7ea6ed4
Step 3 : RUN bash -c 'touch /app.jar'
---> Running in f21125980342
---> 390d62487fa3
Removing intermediate container f21125980342
Step 4 : ENTRYPOINT java -Djava.security.egd=file:/dev/./urandom -jar /app.jar
---> Running in dc04d29c1616
---> 40ac0290f2de
Removing intermediate container dc04d29c1616
Successfully built 40ac0290f2de

이미지도 생성 되었으니 실행해보자.
형식은 이렇다.
docker run -p $HOSTPORT:$CONTAINERPORT -t $IMAGE

docker run -p 8080:8080 -t wonwoo/spring-boot-docker
#필자는 외부가 9000이라..
#docker run -p 9000:8080 -t wonwoo/spring-boot-docker

브라우저를 띄우면 성공적으로 됐다.
컨테이너를 한개 더 생성해보자.

docker run -p 8081:8080 -t wonwoo/spring-boot-docker
#docker run -p 9001:8080 -t wonwoo/spring-boot-docker

브라우저를 띄워서 다시 보자
두개 다 정상적으로 올라왔다.

컨테이너정보를 확인해보자

docker ps

CONTAINER ID        IMAGE                         COMMAND                CREATED             STATUS              PORTS                    NAMES
2296052db0f5        wonwoo/spring-boot-docker   "java -Djava.securit   6 minutes ago       Up 6 minutes        0.0.0.0:9001->8080/tcp   trusting_turing      
d927a7115967        wonwoo/spring-boot-docker   "java -Djava.securit   7 minutes ago       Up 7 minutes        0.0.0.0:9000->8080/tcp   distracted_galileo

요런식으로 두개가 올라와 있다.
한개를 정지해보자
정지하는건 docker stop $CONTAINER_ID

docker stop d927a7115967

다시 확인해보면

CONTAINER ID        IMAGE                         COMMAND                CREATED             STATUS              PORTS                    NAMES
2296052db0f5        wonwoo/spring-boot-docker   "java -Djava.securit   7 minutes ago       Up 7 minutes        0.0.0.0:9001->8080/tcp   trusting_turing

요렇게 한개만 있다.

다시 실행해보자

docker start d927a7115967

다시 실행 된걸 알 수 있다.

간단한 커멘드를 알아보자.

docker images : 이미지를 보여준다.
docker ps -a : 모든 컨테이너 정보다.
docker rm $CONTAINER_ID : 컨테이너를 삭제한다.
docker start $CONTAINER_ID : 컨테이너를 시작한다.
docker stop $CONTAINER_ID : 컨테이너를 중지한다. 
docker logs $CONTAINER_ID : 로그를 확인한다.
docker top $CONTAINER_ID : 프로세서 정보를 확인한다.
docker inspect $CONTAINER_ID : 컨테이너의 모든 정보를 보여준다.(JSON)
docker port $CONTAINER_ID : 포트가 어디로 연결 되었있는지 보여준다.

이 외에도 많은 커멘드가 있다.

docker help 

로 통해 확인하자!

참고 : 만약 docker hub 에 push를 날릴려면 wonwoo를 docker에 가입할때 본인의 name으로 바꾸셔야됩니다!!