도커는 리눅스 컨테이너를 기반으로한 가상화 플랫폼이다. 지금은 가장 유명해지고 보편화되어 리눅스 컨테이너의 대명사가 될 정도로 많이 사용하는 오픈소스 소프트웨어가 되었다. 학교에서 리눅스 강의를 들었을 때 가상화 플랫폼을 이용하여 우분투를 설치해서 강의 내용을 실습하곤 했는데, 도커도 가상화를 해주는 점에서 비슷하다고 할 수 있다.
왜 이러한 가상화 플랫폼을 사용할까? 그 이유는 개발 환경에 있다. 서버 개발을 한다면 개발 시에 사용하는 컴퓨터(개발 환경)이 있고 그 코드를 배포하는 또는 운영하는 배포용 컴퓨터(다른 개발 환경을 가진 컴퓨터(서버)가 존재할 것이다.
모든 소프트웨어는 버전이 존재하고 버전 업을 할 때마다 호환이 되지 않는 경우가 생긴다. 따라서 개발용 환경과 배포용 환경이 100% 일치할 필요가 있다. 따라서 만약 새로운 개발자가 팀에 합류한다면 배포용 머신의 버전에 따라 모든 개발 환경을 동일하게 설치할 필요가 있다.
그렇다면 이런 환경을 어딘가에 문서화 해놓아야 하고 개발용 컴퓨터 역시 그 문서를 바탕으로 하나하나 설치를 해나갈 것이다.
하지만 회사의 규모가 크면 클수록 사용하는 프로그램이 한 두개가 아닐 것이고 이를 전부 똑같이 설치하는데는 긴 시간이 걸리고 실수할 확률이 높다. 도커는 이러한 문제를 가상 머신보다 더 유연하게 해결해준다.
지금부터 도커의 개념과 간단한 사용 방법에 대해 알아보도록 하겠다.
도커는 이미지와 컨테이너라는 개념을 사용하여 위에 언급한 문제를 해결한다. 이미지는 위에서 말한 환경을 적어둔 문서와 비슷하다. Dockerfile
이라는 파일의 문법에 따라 설치할 소프트웨어와 커맨드 등을 문서화한다.
그리고 배포 또는 개발할 컴퓨터에서 그 이미지를 가져와서 컨테이너화를 하면 손쉽게 환경을 만들 수 있다. 도커는 이러한 컨테이너를 도커 레이어 위에 띄우는데, 여기서 가상 머신과의 차이점이 생긴다.
가상 머신을 사용해본적이 있다면 알지만 기본적으로 OS위에 OS를 올린다. 이렇게 했을 경우 컴퓨터의 성능이 뛰어나지 않고 또 GUI까지 적용한다면 굉장히 느리다는 것을 알 수 있는데, 가상 머신은 이렇게 메인 OS 위에 개별적인 OS들이 설치되어 각각 용량, 실행시간에 있어서 도커에 비해 불리하다고 할 수 있다.
컨테이너는 각각 개별적인 프로세스, 네트워크 인터페이스를 마치 가상 머신처럼 가지고 있다. 하지만 가상 머신과는 다르게 OS를 가지고 있지 않는다. 즉 도커에서는 OS 위에 도커 레이어를 가지고 있으므로 다른 OS에서도 똑같이 도커의 컨테이너가 작동할 수 있도록 해준다.
도커를 사용한 경우에는 무거운 OS를 설치할 필요도 없고 그 OS에 설치될 파일들도 도커 이미지를 통해 블루 프린트처럼 다 설계가 되어있으므로 빠르고 쉽게 환경을 설정할 수 있다는 장점이 있다.
도커는 OS 마다 설치 방법이 다른데, 일반적으로 윈도우는 여기서 설치할 수 있다. 설치하면 wsl2
를 깔아야 한다고 나오는데, 전부 설치해주면 된다.
설치 중에 재부팅해야할 일이 많습니다.
리눅스에서는 우분투 기준으로 아래 명령어를 통해 설치할 수 있다.
sudo apt update
sudo apt install apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable"
sudo apt update
apt-cache policy docker-ce
// 도커 설치
sudo apt install docker-ce
// 도커 실행
sudo systemctl start docker
도커를 설치하고 docker --version
을 통해 설치가 잘 되었는지 확인할 수 있다.
만약 wsl2 환경에 도커를 설치하고 싶다면 마이크로 소프트의 가이드에 따라서 도커를 설치할 수 있다.
지금부터 간단히 도커를 로컬 환경에서 실행해보도록 하겠다. 먼저 사용할 서버 파일을 작성할 것인데, 여기서는 스프링 부트를 기준으로 하겠다. 다른 프로그래밍 언어도 도커 파일만 수정해준다면 전부 사용이 가능하다.
먼저 간단히 프로세스를 설명하자면
먼저 서버 파일은 간단한게 start.spring.io
에서 spring-web
디펜던시만 추가하여 가져왔다. 그리고 메인 파일에
@SpringBootApplication
@RestController
public class DockerpracticeApplication {
@GetMapping("/")
public String hello(){
return "Hello Docker";
}
public static void main(String[] args) {
SpringApplication.run(DockerpracticeApplication.class, args);
}
}
이렇게 간단하게 작성해준다. 그리고 실행하고 localhost:8080
에 접속하면 Hello Docker
를 볼 수 있다. 이 방식은 필자 기준으로 자바 11버전의 코드들을 jar
파일로 빌드하여 실행 가능한 상태로 만들고 실행한 것과 같은 결과이다.
그렇다면 이제 이러한 작업을 도커가 알아서 할 수 있도록 Dockerfile
이라는 문서를 작성해주면 된다.
먼저 application.properties
에 server.port=9091
이라는 코드를 추가한다. 잠시 후 스프링 부트와 도커의 포트를 매핑할 때 구분이 될 수 있도록 바꿔주었다.
그리고 그레이들 기준으로 build.gradle
파일에
bootJar {
archiveName("spring-docker.jar")
}
위 코드를 추가하여 빌드되는 jar
파일의 이름을 바꿔준다. 메이븐의 경우에는 플러그인 쪽에
<finalName>spring-docker.jar</finalName>
을 추가해주면 된다.
그리고 그레이들이든 메이븐이든 프로젝트 코드를 빌드하여 jar
파일의 형태로 만들어준다.
마지막으로 프로젝트의 루트 폴더에 Dockerfile
이라는 이름으로 파일을 작성한다. 대소문자 구분에 주의하며 철자가 틀리면 안된다.
FROM openjdk:11-jre-slim-buster
ADD build/libs/spring-docker.jar spring-docker.jar
EXPOSE 9091
ENTRYPOINT ["java", "-jar", "/spring-docker.jar"]
내부에는 위와 같이 작성한다.
그리고 이 프로젝트를 이미지화 한다음 컨테이너에 넣고 실행을 해주면 된다.
프로젝트 루트에서 아래와 같은 명령어를 실행해준다.
docker build -t docker-spring .
docker-spring
이라는 이름으로 이미지를 만드는 명령어 인데, 마지막에 .
를 추가해주어야프로젝트 루트파일에 있는 Dockerfile
을 찾을 수 있다.
docker images
위 명령어를 통해 이미지가 잘 빌드되었는지 확인할 수 있다.
docker run -p 9092:9091 docker-spring
위 명령어를 통해 이미지를 컨테이너화 시킬 수 있는데 docker-spring
이라는 이미지를-p
옵션을 통해 컨테이너 내부에 실행되는 스프링의 포트인 9091을 컨테이너 외부에 접근하는 9092에 매핑을 해준다.
이제 localhost:9092
에 접속하면 정상적으로 도커 컨테이너 위에서 스프링 부트 서버가 돌아가는 것을 확인할 수 있다.
먼저 도커 허브 에 계정을 만들어준다. 깃 허브와 비슷하게 동작하는데 리포지토리 대신 도커 이미지를 저장해두는 곳이라고 생각하면 된다.
회원가입이 완료되면 프로젝트 루트 폴더에서 먼저 docker login
을 통해 로그인을 진행해준다.
docker rm -f `docker ps -a`
docker rmi -f `docker images`
그리고 위 두 명령어를 통해 모든 컨테이너와 이미지를 삭제해준다.
그리고 다시 이미지를 빌드해주는데,
docker build -t <도커허브이름>/docker-spring .
위와 같은 형식으로 도커 이미지를 만들어준다. 그리고
docker push <도커허브이름>/docker-spring
push
명령어를 통해 이미지를 도커 허브에 올려준다. 모든 프로세스가 완료되고 도커 허브의 리포지토리를 확인하면 docker-spring
이라는 이름으로 리포지토리가 생성된 것을 확인할 수 있다.
이제 다른 컴퓨터 또는 다른 환경으로 개발 환경을 이동하자. 가장 간단한 방법으로 aws의 ec2 인스턴스를 실행하는 방법이 있는데, ec2의 실행 방법은 여기에 자세한 방법을 올려두었다.
위에서 리눅스 기준 도커 설치 방법을 통해 도커를 설치하고
sudo docker run -p 9097:9091 <도커허브이름>/docker-spring
를 사용하면 먼저 도커는 로컬에 <도커허브이름>/docker-spring
이라는 이미지가 있는지 확인하고 없으면 도커 허브에서 가져오도록 동작하는데, 로컬에서 빌드한 이미지를 도커 허브에 올렸으므로 다른 환경(여기서는 ec2)에서도 우리가 빌드했던 이미지를 가져와서 실행하게 될 것이다.
보안 그룹에서 인바운드 규칙에 9097번 포트를 열어주고 퍼블릭 ip:9097
에 접속하면 우리가 올린 서버를 확인할 수 있다.
정말 간단하게 로컬에서 만든 서버를 다른 환경에서 실행할 수 있었다.