MEMO

Springboot + nginx 를 Docker 를 이용해 배포하기 본문

Docker

Springboot + nginx 를 Docker 를 이용해 배포하기

by_dev 2019. 12. 4. 17:33

Springboot 를 Docker 를 이용해 배포하기

기본적인 Springboot 프로젝트를 만들어 image 로 생성해보기 위해 새로운 Springboot 프로젝트를 생성하였다. 기본 Springboot 프로젝트 설정에 다음과 같이 접속 확인을 위한 String 출력 소스만 추가하였다.

//프로젝트 구조
.

- Dockerfile
- pom.xml
- src
   L main
     L java
      L by.example.docker
        L DockerApplication.java
                
 ... 이하 생략

DockerAppication.java 에는 다음과 같이 RequestMapping 만 추가하였다.

package by.example.docker;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
public class DockerApplication {

    @RequestMapping("/")
    public String home() {
        return "Hello Docker World";
    }

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

}

그 다음으로 pom.xml 에 plugin 과 properties 를 추가한다.

<properties>
        <docker.image.prefix>docker-spring</docker.image.prefix>
</properties>

<build>
        <plugins>       
            <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>dockerfile-maven-plugin</artifactId>
                <version>1.4.9</version>
                <configuration>
                    <repository>${docker.image.prefix}/${project.artifactId}</repository>
                </configuration>
            </plugin>
        </plugins>
    </build>

여기까지 완료하였다면 .jar 파일을 만들어 준다. 필자는 maven 을 이용하여 .jar 파일을 만들었기 때문에 다음의 명령어를 사용하였다.

mvn package && java -jar target/docker-0.0.1-SNAPSHOT.jar

만들어진 프로젝트가 제대로 작동하는지 확인 후, Dockefile 을 만든다. 

FROM openjdk:8-jdk-alpine
VOLUME /tmp
ARG JAR_FILE=target/docker-0.0.1-SNAPSHOT.jar
COPY ${JAR_FILE} docker-springboot.jar
EXPOSE 8080
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/docker-springboot.jar"]

openjdk8 이미지를 사용하였으며, 컨테이너 내부에서 8080 포트를 사용하도록 설정하였다. 해당 이미지를 빌드하기 위해 다음의 명령어를 사용한다.

docker image build -t springboot:0.1 .

이미지 빌드가 성공적으로 되었다면 image 를 실행해 봄으로써 잘 작동하는지 확인할 수 있다. 

docker image run --name springboot-docker springboot:0.1

잘 작동하는게 확인이 되었다면 springboot 를 단순히 image 로 생성하여 Docker 를 이용해 작동하는것은 완료되었다. nginx 와 함께 docker-compose 를 이용해 배포해보도록 한다.

Springboot + nginx + Docker 를 이용한 배포

nginx 설정을 위한 파일이 들어있는 nginx 디렉토리와 docker-compose.yml 파일이 추가되었다. 여기에서 필자는 nginx 환경설정 파일을 따로 만들어 새로운 nginx image 를 만들기 위해 nginx_Dockerfile 을 만들었다. 공식적으로 제공되는 nginx 이미지를 사용하는 경우, nginx_Dockerfile 등은 사용하지 않아도 된다.

//프로젝트 구조
.

- Dockerfile
- docker-compose.yml
- pom.xml
- nginx
   L nginx_Dockerfile
   L conf.d
     L app.conf
     L nginx.conf
- src
   L main
     L java
      L by.example.docker
        L DockerApplication.java
                
 ... 이하 생략

위에서 언급한대로 nginx_Dockerfile 을 만들어서 진행하였기 때문에 우선 nginx image 를 생성하여야 한다. nginx_Dockerfile 과, 관련된 app.conf, nginx.conf 파일은 다음과 같다. 

#nginx_Dockerfile
FROM nginx:1.11

RUN rm -rf /etc/nginx/conf.d/default.conf

COPY ./nginx/conf.d/app.conf  /etc/nginx/conf.d/app.conf
COPY ./nginx/conf.d/nginx.conf  /etc/nginx/nginx.conf

VOLUME ["/data", "/etc/nginx", "/var/log/nginx"]

WORKDIR /etc/nginx

CMD ["nginx"]

EXPOSE 80
#app.conf
server {
    listen       80;
    listen      [::]:80;

    server_name  "";

    access_log off;

    location / {
            proxy_pass http://docker-springboot:8080;
    	    proxy_set_header Host $host:$server_port;
            proxy_set_header X-Forwarded-Host $server_name;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }

}

여기에서 docker-springboot:8080 은 docker-compose 에서 설정할 springboot 서비스의 이름을 필자는 docker-springboot 로 설정하였기 때문에 다음과 같은것이다. service 의 명칭을 test 로 하는 경우 test:8080 으로 입력하면 된다.

#nginx.conf
daemon off;
user  www-data;
worker_processes  2;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
    use epoll;
    accept_mutex off;
}

http {
    include       /etc/nginx/mime.types;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    client_max_body_size 300m;
    client_body_buffer_size 128k;

    gzip  on;
    gzip_http_version 1.0;
    gzip_comp_level 6;
    gzip_min_length 0;
    gzip_buffers 16 8k;
    gzip_proxied any;
    gzip_types text/plain text/css text/xml text/javascript application/xml application/xml+rss application/javascript application/json;
    gzip_disable "MSIE [1-6]\.";
    gzip_vary on;

    include /etc/nginx/conf.d/*.conf;
}

nginx_Dockerfile 을 image 로 빌드하기 위해서는 다음의 명령어를 사용한다.

docker image build -t springboot-nginx:0.1 -f nginx_Dockerfile .

마지막으로 docker-compose.yml 파일을 작성 후 docker-compose up 명령어를 실행시켜주면 완료된다.

version: "3"
services:
  nginx:
    image: springboot-nginx:0.1
    ports:
      - 80:80
    depends_on:
      - docker-springboot
  docker-springboot:
    build: .
    expose:
      - 8080

depends_on 명령어를 이용해서 docker-springboot 가 우선 실행한 이후 nginx 서비스가 실행되도록 설정하였다. 위에서 빌드한 springboot-nginx:0.1 이미지를 통해 빌드하였으며 docker-springboot 는 .에 만들어져있는 Dockerfile 을 재빌드하도록 설정하였다. docker-springboot 서비스의 경우 8080포트를 이용해 컨테이너 내부에서 접근이 가능하며, 컨테이너 외부에서는 접근이 불가능하다. nginx 의 80 포트를 이용해 접속해면 nginx 가 docker-springboot 로 보내주도록 설정하였다. 

설정과 배포가 성공적으로 완료되었다면 localhost:80/ 을 접속하였을때 "Hello Docker World" 라는 문구가 나오는 화면이 나와야 한다.

 

해당프로젝트는 github(https://github.com/bypark-dev/docker-springboot) 에 올라가 있다.

Comments