[docker] docker로 회사 개발 서버 구축하기 02 - docker 컨테이너 사용하기

KIM Jongwan·2024년 9월 30일
0
post-thumbnail

이전 포스트에서는 docker host로 사용될 서버를 구성하고, docker 프로세스를 설치 및 실행해보았습니다. 이번 포스트를 통해 docker host서버 위에 새로운 우분투 컨테이너를 생성하고 ssh를 이용해 접속하는 방법을 알아보도록 하겠습니다.

docker hub & image

docker container는 사전에 빌드 된 image 정보를 바탕으로 생성됩니다. 사용 가능한 image들은 docker hub를 통하여 저장되고 공유됩니다. 프로그래머는 자신이 빌드한 image를 모두가 사용할 수 있도록 docker hub에 공유할 수도 있고 특정 사용자만 이용할 수 있는 private 한 저장소를 구축하며 공유할 수 있습니다.

docker hub에 접속하여 사용할 수 있는 ubuntu image를 검색해봅시다.
https://hub.docker.com/_/ubuntu

등록되어있는 우분투의 버전이 위와 같이 명시되어있습니다. 그럼 ubuntu 이미지를 다운로드(pull)해보겠습니다. 그 전에 현재 docker host에서 사용 가능한 이미지의 목록을 조회하기위해 docker images명령어를 사용해보겠습니다.

$ docker images
REPOSITORY              TAG       IMAGE ID       CREATED             SIZE
$

현재 다운받은 이미지가 존재하지 않는 것을 볼 수 있습니다.
이제 ubuntu 22.04 이미지를 다운로드 해보겠습니다.


docker pull

docker pull 명령어는 docker hub에 업로드되어있는 이미지를 현재 docker host로 가져옵니다. docker pull {image}:{version} 과 같이 사용할 수 있습니다. version을 명시하지 않을 경우 자동으로 latest 버전의 이미지가 다운로드 됩니다.

$ docker pull ubuntu:22.04
22.04: Pulling from library/ubuntu
6414378b6477: Pull complete
Digest: sha256:58b87898e82351c6cf9cf5b9f3c20257bb9e2dcf33af051e12ce532d7f94e3fe
Status: Downloaded newer image for ubuntu:22.04
docker.io/library/ubuntu:22.04

## version을 명시하지 않았을 경우
$ docker pull ubuntu
Using default tag: latest
latest: Pulling from library/ubuntu
dafa2b0c44d2: Pull complete
Digest: sha256:dfc10878be8d8fc9c61cbff33166cb1d1fe44391539243703c72766894fa834a
Status: Downloaded newer image for ubuntu:latest
docker.io/library/ubuntu:latest

가져온 image가 잘 저장되어있는지 확인해보겠습니다.

$ docker images
REPOSITORY              TAG       IMAGE ID       CREATED             SIZE
ubuntu                  latest    b1e9cef3f297   4 weeks ago         78.1MB
ubuntu                  22.04     97271d29cb79   2 weeks ago         77.9MB

docker ps & run

image가 정상적으로 받아졌다면 image를 사용하여 container를 생성해야합니다. docker ps 명령어는 현재 구동중인 container의 목록을 출력합니다.

$ docker ps
CONTAINER ID   IMAGE                 COMMAND                  CREATED             STATUS             PORTS                                                                                  NAMES

구동중인 container가 존재하지 않기 때문에 아무 목록도 출력되지않습니다. -a 옵션과 함께 다시 한번 출력해보겠습니다.

$ docker ps -a
CONTAINER ID   IMAGE                 COMMAND                  CREATED             STATUS            	 	PORTS              NAMES
e39c9c5d19c4   ubuntu-image:1.0      "/bin/sh -c 'service…"   7 days ago          Exited 1 days ago             				container-ubuntu

-a 옵션은 container의 실행 유무와 상관 없이 현재 host에 존재하는 모든 container를 조회하는 옵션입니다.

앞서 다운로드한 우분투 이미지(ubuntu:22.04)로 컨테이너를 생성해보겠습니다. 컨테이너 생성을 위한 명령어는 docker run <옵션> <이미지> <명령> <매개 변수> 과 같이 사용합니다. 우선은 아무 옵션도 주지 않고 실행시킬 이미지만 명시해보겠습니다.

$ docker run ubuntu:22.04
$ docker ps -a
CONTAINER ID   IMAGE                    COMMAND                  CREATED         STATUS                     PORTS                                                                                  NAMES
030098545b05   ubuntu:22.04             "/bin/bash"              4 seconds ago   Exited (0) 3 seconds ago                                                                                          charming_shannon

의도한대로 컨테이너가 생성되었지만 STATUS를 확인해보니 컨테이너가 실행되지 않고 종료되었음을 확인할 수 있습니다. docker container는 별도 옵션 없이 실행하면 모든 표준 입력이 종료되면 컨테이너 또한 종료됩니다.

컨테이너의 구동 상태를 유지하기 위해서는 run 명령어와 함께 옵션을 지정해주어야합니다.

docker run 명령어 옵션

run 명령어 옵션들 중 자주 사용되는 명령어를 살펴보겠습니다.

  • --name: 실행될 컨테이너의 이름을 지정합니다. 컨테이너를 특정하여 작업이 필요할 경우 지정된 name을 활용할 수 있습니다. (생략 시 임의 name 지정)

  • -i(또는 --interactive): 컨테이너의 표준 입력을 활성화합니다. 컨테이너와 연결되지 않은 상태에서도 활성화된 표준 입력을 유지합니다.

  • -t(또는 --tty): 가상 터미널(tty)을 할당하여 사용자의 표준 입력을 컨테이너로 전달합니다.

  • -d(또는 --detach): 컨테이너를 백그라운드에서 실행합니다.

  • -p(또는 --publish): 호스트 PC와 컨테이너 간 포트 포워딩 설정이 필요할 경우
    -p <호스트포트>:<컨테이너포트> 와 같이 지정합니다.

  • -v(또는 --volume): 호스트 PC와 컨테이너 간 연결될 디렉토리(마운팅)를 설정합니다.

  • -e(또는 --env): 컨테이너 내에서 사용될 환경 변수를 지정합니다.

생성된 컨테이너가 구동 상태를 유지하고 Bash를 사용하여 명령어 입력이 필요할 경우

## 구동 상태 유지, 생성된 컨테이너 이름을 'container-ubuntu'로 지정
$ docker run -itd --name container-ubuntu ubuntu:22.04

## 구동중인 컨테이너 확인
$ docker ps
CONTAINER ID   IMAGE                 COMMAND                  CREATED             STATUS             PORTS              NAMES
e39c9c5d19c4   ubuntu-image:1.0      "/bin/sh -c 'service…"   4 seconds ago       Up 3 seconds ago              		container-ubuntu

위와 같이 실행된 컨테이너가 구동상태를 유지하고 있는 것을 확인할 수 있습니다.

실행중인 container로 접속하기

실행중인 컨테이너에서 실행할 명령어를 전달하고 싶을 때 docker exec를 사용합니다.
exec는 docker exec {container name} {실행할 명령어}와 같이 사용할 수 있습니다.
앞서 실행한 컨테이너에서 간단한 echo 명령어를 실행해보겠습니다.

$ docker exec container-ubuntu echo "hello"
hello
$

exec로 실행한 echo 명령어가 실행되었습니다. 위와같이 단발성 명령어를 실행할 때는 별도 옵션 없이 exec만으로 명령어를 실행할 수 있습니다.
하지만 직접 컨테이너에 접속하여 여러가지 작업이 필요할 경우 -it옵션을 추가하고 컨테이너 내의 bash를 실행해주면 됩니다.

$ docker exec -it container-ubuntu /bin/bash
root@e39c9c5d19c4:/#

-it 옵션을 추가하고 bash를 실행하니 컨테이너의 bash 쉘이 실행되었습니다.

nginx 설치 및 접속

클라이언트가 도커 호스트 PC에게 80포트로 요청을 보내면 실행되고있는 컨테이너 중 Nginx가 구동중인 컨테이너로 요청을 포워딩해보는 간단한 실습을 진행해보겠습니다.

컨테이너 생성 (포트포워딩)

이전에 다운로드 받은 ubuntu:22.04이미지를 활용하여 컨테이너를 생성하겠습니다. 다만 이번에는 호스트 PC의 80번 포트로의 요청을 생성된 컨테이너의 80번 포트로 포워딩해주는 옵션을 추가해보겠습니다.

$ docker run -itd -p 80:80 --name ubuntu-nginx ubuntu:22.04
f390de72ac1dcd57b27ca7c0c2a19601c78b58ae4e1d32a90d591d144e58c6dc
$ docker ps 
CONTAINER ID   IMAGE                    COMMAND                  CREATED         STATUS                  PORTS                                                                                  NAMES
f390de72ac1d   ubuntu:22.04             "/bin/bash"              3 seconds ago   Up 2 seconds            0.0.0.0:80->80/tcp, :::80->80/tcp                                                      ubuntu-nginx

80:80 포트포워딩 설정이 완료된 우분투 컨테이너가 동작하고있는 것을 확인할 수 있습니다. 컨테이너에 접속하여 nginx 설치를 진행해보도록 하겠습니다.


$ docker exec -it ubuntu-nginx /bin/bash
root@f390de72ac1d:/# apt update
Get:1 http://archive.ubuntu.com/ubuntu jammy InRelease [270 kB]
Get:2 http://security.ubuntu.com/ubuntu jammy-security InRelease [129 kB]
Get:3 http://archive.ubuntu.com/ubuntu jammy-updates InRelease [128 kB]

......

root@f390de72ac1d:/# apt-get install -y nginx
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
  fontconfig-config fonts-dejavu-core iproute2 libatm1 libbpf0 libbrotli1 libbsd0 libcap2-bin libdeflate0 libelf1 libexpat1 libfontconfig1 libfreetype6 libgd3 libicu70 libjbig0 libjpeg-turbo8 libjpeg8 libmaxminddb0 libmd0 libmnl0
  libnginx-mod-http-geoip2 libnginx-mod-http-image-filter libnginx-mod-http-xslt-filter libnginx-mod-mail libnginx-mod-stream libnginx-mod-stream-geoip2 libpam-cap libpng16-16 libtiff5 libwebp7 libx11-6 libx11-data libxau6 libxcb1
  libxdmcp6 libxml2 libxpm4 libxslt1.1 libxtables12 nginx-common nginx-core ucf
  
  ......
  
Setting up nginx (1.18.0-6ubuntu14.5) ...
Processing triggers for libc-bin (2.35-0ubuntu3.8) ...
root@f390de72ac1d:/# service nginx status
 * nginx is not running
root@f390de72ac1d:/# service nginx start
 * Starting nginx nginx                                   
root@f390de72ac1d:/# service nginx status
 * nginx is running
root@f390de72ac1d:/# exit
$

우분투 컨테이너에 nginx가 설치되었고 프로세스가 실행중임을 확인하였습니다.
이제 크롬을 통해 호스트PC의 80포트로 요청을 보내고 nginx의 인덱스 페이지가 노출되는것을 확인해봅시다.

마무리

기본적인 docker 사용 방법을 알아보고 간단한 실습을 진행하였습니다. docker에서는 컨테이너 당 하나의 프로세스만을 구동하도록 권장하고있습니다. (예: 엔진엑스 컨테이너, API 서비스 컨테이너, 젠킨스 컨테이너) 앞서 진행해본 예시대로라는 컨테이너 하나(우분투)에 여러개의 프로세스(엔진엑스, API 서비스 기타 등등)가 실행되므로 권장되는 형태와는 다름을 말씀드립니다.

저희 회사에 구축되어진 개발 환경 또한 하나의 ubuntu, 하나의 rocky linux 서버를 제외하고는 모두 컨테이너당 하나의 프로세스만 구동하는 형식으로 사용하고있습니다.

간단한 사용방법이니만큼 자원을 공유하거나 별도의 네트워크 환경을 구축하는 등 설정은 진행하지 않았습니다. 이후 포스팅에서는 docker의 응용 사용법과 k8s와 결합한 컨테이너 오케스트레이션까지 진행해보도록 하겠습니다.

profile
3년차 백앤드 개발자입니다.

0개의 댓글