본문 바로가기

4.개발 및 운영 환경

[docker] docker 간단하게 사용해보기

들어가기

도커를 제대로 활용하려면 어느 정도 경험을 가진 시스템 관리자나 개발자가 사용하기에 적합하고 단순 시스템을 구성할 때에 사용하기에는 초기 노력이 많이 들기 때문에 사용하기 쉽지가 않다.
Java의 spring인 경우는 기본 실행환경을 구성하기 위해 많은 노력이 든다. 그렇기에 시간이 걸리지만 도커를 사용하는게 배포관리에 더 효율적일 수 있다. 그러나 spring boot를 사용하면서 기본 실행환경 구성에 많은 노력이 필요없다. 그래서 docker로 구성하면 배포하는데 단계가 더 늘어나는 결과를 가져온다. 물론 전자 이야기는 독립형 서버를 구성할 경우이다. 많은 여러 서버를 구성할 경우는 달라진다.
docker를 사용할 경우 장점은 있다. 어떤 서버는 환경 구성하는데 해야할 작업들이 많다. 설치할 프로그램이나 라이리브러리와 시스템 환경설정을 해줘야한다. 이를 docker로 할 경우 미리 구성해놓은 설정으로 바로 서버를 구동할 수 있다. 특히, 필요로하는 프로그램을 대부분 다운로드해서 사용할 수 있기 때문에 dockerfile만 있다면 서버를 실행할 수 있다. 매력적일 수 밖에 없다.

작성자: ospace114@empal.com, http://ospace.tistory.com/

docker?

docker를Solomon Hykes에 의해 처음 발표하면서 알려졌다. docker는 가상화 기반으로 컨테이너관리 오픈소스 가상화 플랫폼이다. 가상화는 이전에 vmware나 virtual box가 있다. 이는 OS가상화로 새로운 시스템(VM, virtual machine)를 가상으로 만들어서 사용하는 형태로 메모리와 CPU를 독립적으로 할당해서 사용하게 된다. 이런 방식은 새로운 VM에 OS를 새로 올리고 프로그램을 실행하는 방식이기 때문에 바로 실행하는 프로그램에 비해 성능이 느려진다.
이로 인해 프로세스 격리 방식이 등장했다. 이는 실행하는 프로세스를 격리하여 분리된 시스템에서 실행하는 방식으로 별도 가상화된 OS없이 바로 실행하는 방식으로 성능이 빨라지고 CPU나 메모리도 독립적으로 할당해서 사용하지 않기에 리소스 사용측면에서도 효율적인다.
실제 사용 측면에서 VM를 할당해서 사용하는 것과 거의 동일하면서 성능하락도 거의 없고 리소스 사용도 효율적이기 때문에 매우 매력적이다.

docker container와 image

도커에서 컨테이너와 이미지라는 용어가 있다. 이미지는 실행에 필요한 파일과 설정이 포함된 파일로 변하지 않은 상태를 가진다. 컨테이너는 이미지가 실행한 상태로 추가 또는 변경된 상태가 저장되기 때문에 변할 수 있는 상태이다. 운영체제에 비유하면 이미지는 실행파일이라고 보면되고 컨테이너는 프로세서라고 보면 된다.
docker에서는 이미지를 다운로드 받을 수 있도록 제공하고, 각자 이미지를 받아서 필요한 추가 구성을 통해 컨테이너로 실행하게 된다. 이런 이미지를 관리를 하는 곳이 Docker hub이고 직접 관리하고 싶다면 Docker Registry에서 할 수 있다.

docker image은 os부터 어플리케이션까지 아주 다양한 image을 사용할 수 있다. 그리고 사용자들이 직접 만들어서 image을 공유할 수 있기 때문에 그 개수는 매우 많다. 그렇기 때문에 원하는 것을 선택해서 사용하는게 문제이고 더 큰 문제는 만들어진 image에 대한 안전성에 의심을 가질 수 있다. 그래서 잘 알려지거나 믿을수 있는 곳에서 만들어진 image를 사용하는게 좋다.

docker가 더욱 인기있게 만든 것은 docker layer로서 레이어 형태로 image을 저장하는 방식이다. 새로운 image은 새로 만드는게 아니라 기존 기본 image에서 추가되는 항목만 레이어 형태로 추가하는 방식이다. 그렇기 때문에 중복을 최소화하고 필요한 부분만 다운받아서 사용하기 때문에 아주 효율적으로 image을 관리할 수 있다.

간단한 사용

기존에 만들어진 image로 docker를 활용해보자. 아래 내용은 이미 docker가 설치되어있다는 가정으로 설명하겠다.
사용한 docker는 dokcer desktop 버전 3.3.1 기준이다.

docker를 설치하면 화면에 아래 명령이 보인다. 아래 명령을 도스창을 열어서 입력해보자.

docker run -d -p 80:80 docker/getting-started

"docker"는 실행파일이고 run은 명령어이다. -d는 detached 모드로 컨테이너를 실행하라는 의미이고 -p 80:80은 내부 port 80을 외부 port 80으로 연결하라는 옵션이다. 그리고, "docer/getting-started"가 image 이름으로 버전이 명시되어 있지 않기 때문에 기본 값 "lastest"을 사용해서 image을 선택한다. 버전을 명시적으로 지정할 수 있다.

ubuntu
ubuntu:latest
ubuntu:18.04

첫번째와 두번째는 같은 의미로 버전을 생략하면 lastest가 기본으로 선택된다. 세번째는 버전 18.04를 선택한다. 버전에 대한 표기 형태는 docker image를 만드는 사람에 따라 달라질 수 있기 때문에 사용하려는 image을 먼전 확인하는 걸 추천한다.

container을 확인하려면 아래 링크에서 원하는 container명을 검색하면 된다.

실행하면 처음 실행하는 경우 아래처럼 콘솔에 출력된다. 실행 결과를 보면 "docker/getting-started:lastest"로 찾고 있다.

끝나면 container가 실행되고 실행중인 container를 확인하려면 다음 명령을 입력한다.

docker ps

docker container 목록이 출력된다.

docker desktop을 사용해서 container를 실행하거나 상태를 확인할 수 있다. docker desktop 실행해서 살펴보면 Containers / Apps 항목에 앞에서 실행된 container가 보인다.

실행된 container를 잘 보면 port가 80으로 표시되어 있다. 이는 container에서 서비스가 실행 중이고 port가 80으로 연결할 수 있다는 의미이다. 그럼 브라우저로 "localhost"로 접속해보자. 그러면 아래와 같은 화면이 보인다.

이렇게 해서 간단하게 서비스 image을 다운받아서 실행했다. 매우 간단하게 서비스를 실행할 수 있다.
실행중인 container에 쉘로 접속해보자. exec 명령어로 쉘을 실행할 수 있다.

docker exec -it a34369627f55 sh

간혹 아래와 같은 에러 메시지가 출력될 수 있다. 이 경우는 windows용 git을 MinTTY 설치한 경우 발생하는 문제라고 한다.[4]

the input device is not a TTY.  If you are using mintty, try prefixing the command with 'winpty'

이때는 당황하지 말고 명령어 앞에 winpty를 입력해서 실행한다.

winpty docker exec -it a34369627f55 sh

또 간혹 특정 사용자 ID로 쉘을 실행할 경우도 있다. 아래는 root로 접속하는 예제이다.

docker exec -u 0 -it a34369627f55 sh

다른 명령어들

  • images : 다운로드된 이미지 목록 확인
    • 예) docker images
  • pull : 이미지 다운로드만 받음
    • 예) docker pull ubuntu
  • stop : container 실행 중지
    • 예) docker stop a34369627f55
  • rmi: image 삭제
    • 예) docker image ubuntu:latest
  • logs : container 로그 확인
    • 예) docker logs a34369627f55
    • 에) docker logs -f a34369627f55

compose 활용

간단한 docker 명령을 사용해서 image을 다운로드 받고 container을 실행해보았습니다. 매번 명령을 입력하기가 쉽지 않는데 이를 YAML 형식의 설정파일로 관리해주는 툴인 docker compose을 제공하고 있습니다.

간단하게 docker-compose.yml 파일을 만들고 다음을 입력합니다.

version: '2'
services:
    getting-started:
        image: docker/getting-started
        ports:
            - "80:80"
        restart: always

version은 docker-compose의 버전을 의미하며 자세한 내용은 아래 링크를 참고하세요.

아래 명령을 입력하면 실행된다. 자동으로 현재 디렉토리에 있는 docker-compose.yml을 찾아서 실행한다.

docker-compose up -d

up은 container 실행하는 명령이고 down은 container 중지하는 명령이다. 뒤에 -d은 detached 모드로 실행하는 명령으로 없으면 명령이 실행된채로 빠져나오지 않게 된다.

실행을 중지하려면 아래 명령을 실행하면 된다.

docker-compose down

docker compose에 대한 자세한 내용은 아래 링크를 참고하세요.

간단한 image 만들기

docker image를 만들기 위해 Dockerfile이라는 DSL(domain-specific language)로 정의된 파일을 만들어야 한다.
다음 예제는 홈페이지를 만들어서 nginx라는 웹서버를 사용해서 웹서비스를 제공하는 image을 생성하려고 한다.

아래는 작업한? HTML 페이지인 index.html파일이다.

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
    <title>Now</title>
</head>
<body>
    <h1></h1>
    <script>
        var h1 = document.querySelector('h1');
        setInterval(function(){ h1.innerHTML = new Date() }, 1000);
    </script>
</body>
</html>

이 파일을 가지고 nginx라는 웹서버를 설치하고 웹를 실행할 수 있는 docker image을 생성해보자. 먼저 ubuntu에서 실행하는 환경을 구성해보자. 일단 ubuntun는 설치되어 있다고 가정하겠다. windows 10 환경이라면 WSL에서 실행할 수 있는 ubuntu가 있다. Microsoft Store에서 설치할 수 있다.

index.html파일은 ubuntu에 자신의 홈디렉토리에 있다고 가정하겠다.

아마도 설치 및 실행되는 과정은 다음과 같다.

sudo apt-get update
sudo apt-get install nginx
sudo cp ~/index.html /var/www/html
sudo nginx

마지막에 nginx를 실행하면 웹서버가 실행되면서 웹브라우저로 "http://localhost/"로 접속하면 다음과 같은 웹 페이지가 보인다.

이런 작업을 docker image에서도 동일하게 진행하게 된다. 단지 표현방법이 다소 틀린 부분이 있을뿐이다.
먼저 현재 html 작업 중인 디렉토리에서 docker image용 기본 파일명인 확장자 없는 "Dockerfile"를 생성한다.
그리고 아래 내용을 입력한다.

FROM ubuntu:20.10
LABEL maintainer="ospace114@empal.com"
RUN apt-get -y update
RUN apt-get install nginx -y

COPY ./index.html /var/www/html

EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

한줄씩 설명하면

  • FROM ubuntu:20.10
    • 기본 image을 지정한다. 여기서는 ubuntu이고 버전이 20.10을 사용한다.
  • LABEL maintainer="ospace114@empal.com"
    • 추가 정보로 작업한 사람에 대한 정보를 입력한다. (옵션)
  • RUN apt-get -y update
  • RUN apt-get install nginx -y
    • 패키지 최신 정보를 갱신하고 nginx를 설치
    • -y 옵션은 항상 yes로 자동으로 설치를 진행하기위해 필요
  • COPY ./index.html /var/www/html
    • 현재 디렉토리에 있는 index.html를 /var/www/html 디렉토리로 복사
  • EXPOSE 80
    • 외부로 노출될 포트를 지정
    • nginx은 웹서버이기에 별도 설정을 하지않았다면 기본 포트인 80을 사용
  • CMD ["nginx", "-g", "daemon off;"]
    • container가 실행되면 실행되는 명령으로 없다면 즉시 종료됨
    • 여기서는 ngnix 웹서버를 실행되면 나머지는 옵션으로 서비스를 제대로 실행하기 위해 추가로 필요함
    • -g는 global 디렉티브 설정으로 "daemon off;"를 적용함

만들어진 Dockerfile로 image을 생성해보자.

docker build -t ospace/web .

web이라는 이름의 image가 생성된다. -t 옵션에 의해 생성되는 image이름을 지정할 수 있다. 버전을 지정하고 싶다면 "web:1.0" 처럼 사용할 수 있다.
생성된 image을 확인하고 싶다면 아래 명령을 입력하면 된다.

docker images

그러면 repository에 ospace/web이라는 image가 보인다.

실행해보자. 그리고 웹브라우저로 "http://localhost/"로 접속하면 웹 페이지를 확인할 수 있다.

docker run -p 80:80 ospace/web

docker image을 생성하다보면 불필요한 image가 생길 수도 있다. 앞의 예에서도 REPOSITORY가 ""이고 IMAGE ID가 "86c41c2d0c5c"인 image가 있는데 삭제해보자.

docker rmi -f 86c41c2d0c5c

기타등등

Windows10에서 docker 설치안되는 경우

먼저 PowerShell을 관리자 권한으로 실행한다.

다음 명령으로 컨테이너 기능을 활성화 합니다.

Enable-WindowsOptionalFeature -Online -FeatureName containers -All

다시 도커를 실치합니다.

컨테이너를 자동으로 실행

docker update --restart=always <container-id>

결론

docker를 사용해서 container를 실행하고, 간편하게 관리하는 docker-compose도 간략하게 살펴보았다. 또한 image을 만드는 방법도 간단하게 살펴보았다. 복잡한 기술을 아주 간단하게 사용할 수 있는게 docker를 장점이고 필요로하는 리소스가 작다는 점도 아주 매력적이다. 여기서는 아주 간단하게 살펴보았기 때문에 자세한 내용은 더 공부가 필요하다.
docker image를 만드는 방법은 리눅스에 대해 잘 알고 있다면 좀더 쉽게 접근할 수 있기 때문에 리눅스 시스템 사용에 대한 부분고 알아두면 도움이 된다.
너무 간단하게 알아보아서 실제 활용에 있어서 어려움이 있지만, docker 접근하는데 조금이나마 도움이 되었으면 한다.ospace.

참고

[1] subicura, 초보를 위한 도커 안내서 - 도커란 무엇인가?, 2017.01.19, https://subicura.com/2017/01/19/docker-guide-for-beginners-1.html
[2] subicura, 초보를 위한 도커 안내서 - 설치하고 컨테이너 실행하기, 2017.01.19, https://subicura.com/2017/01/19/docker-guide-for-beginners-2.html
[3] subicura, 초보를 위한 도커 안내서 - 이미지 만들고 배포하기, 2017,02.10, https://subicura.com/2017/02/10/docker-guide-for-beginners-create-image-and-deploy.html
[4] renuevo, [Docker] Docker 시작하기 - Hello World와 Git Bash, 2020.03.12, https://renuevo.github.io/docker/docker-hello-world/
[5] wijihoon123, Nginx 명령어 모음, 2021.02.10, https://velog.io/@wijihoon123/Nginx-%EB%AA%85%EB%A0%B9%EC%96%B4-%EB%AA%A8%EC%9D%8C

반응형