[Docker] Docker Concepts - 도커의 개념과 명령어

김희정·2023년 2월 2일
4

Docker

목록 보기
1/3
post-thumbnail

💎 들어가며

많은 소프트웨어 기업에서는 Docker를 사용하며, Docker는 차세대를 위한 기술이며, 서버개발자는 필수로 배워야하는 자격요건에 Docker는 항상 있다. Docker가 가상화 기술이라는 건 알았지만, 대체 도커가 뭘까?

이번 포스팅에서는 Docker의 개념에 대해 알아보고 도커 이용해 웹 컨테이너를 만들어봅시다


1. What is Docker?

Docker

Docker란 무엇인가? 데이터 또는 프로그램을 격리시키는 기능을 제공하는 소프트웨어이다.

Docker는 주로 서버에서 사용하는 것이 주 용도이다.


Docker Engine, Container, Image

도커는 다양한 프로그램과 데이터를 각각 독립된 환경에 격리하는 기능을 제공한다. 도커에서의 핵심은 프로그램 격리(isolation) 이라고 한다.

당신은 유지보수를 해본적이 있던가? 회사에 입사하여 유지보수를 시작하면 당신은 프로그램이 얼마나 빠르게 업그레이드되는지 알것이다. 그리고 현재 프로젝트는 얼마나 구닥다리인지도 알것이다.

나는 유지보수를 하면서 nodeJS 지옥을 맛보았다. 내가본 nodeJS는 업데이트 속도가 매우빠르고 호환성이 좋지 않다.. 그래서 버전을 잘못 설치하면 프로그램이 돌아가지 않는다. 근데 또 nodeJS 프로그램은 한 개 밖에 못깔지 아주 미치는 꼴을 보게될것이다.

이때 내가 도커를 알았다면 얼마나 좋았을까?

이런 환경에서 도커 컨테이너로 환경을 구성하면 된다. docker container 내부의 프로그램은 다른 외부/컨테이너에 영향을 미치지 않기 때문에 환경마다 다른 프로그램을 설치할 수 있다.

💡 용어 정리

  • Docker Engine 컨테이너를 생성하고 구동
  • 컨테이너 각각 독립된 환경
  • 이미지 컨테이너를 만들기 위해서는 이미지(snapshot)

Docker의 동작원리 ⚙

일반적으로 Docker는 리눅스 환경 위에서 동작한다.

윈도우나 macOS에서는 VMWare/VirtualBox 등 가상환경 위에서 리눅스 OS를 설치하고 그 위에 도커를 실행하거나

'윈도우 또는 macOS용 도커 데스크톱'처럼 도커를 실행하는 데 필요한 리눅스 운영체제를 포함한 패키지를 설치해 사용한다.

컨테이너는 외부와 완전히 분리돼 있으므로 컨테이너 속에 운영체제의 주변 부분이 따로 들어있다.

  • 일반적인 컴퓨터: 하드웨어운영체제(커널)운영체제 주변부분소프트웨어

  • 도커: 하드웨어운영체제(커널)도커 엔진컨테이너 + 운영체제 주변부분소프트웨어


Docker Hub 👀

도커 허브란? 공식적으로 운영되는 도커 레지스트리 (도커 이미지를 배포하는 서비스)를 의미한다.

도커 허브에는 공개된 컨테이너 이미지가 모여있다. 누구든지 이미지를 등록하고 공개할 수 있다. (아이디만 있다면) ex) 리눅스 배포판

안전한 도커 이미지를 선택하기 위해서는 공식 이미지를 사용하거나 커스텀 이미지를 직접 만들어 사용한다.



2. Docker Command

자, Docker의 개념에 대해 정리해보면 docker의 핵심은 Docker Engine이고, Docker Engine은 Container를 관리한다. 그리고 Container는 각각 독립된 환경을 의미한다.


Docker Engine은 Container를 관리하기 위해 명령어(Command)를 제공한다.
그리고 그 명령어는 docker로 시작한다.

$ docker 커맨드 (옵션) 대상 (인자)

도커 커맨드는 상위 커맨드하위 커맨드가 있다. 상위 커맨드는 때때로 생략 가능하다.

우선 시작에 앞서, 가장 기본적인 명령어를 쳐보자.

명령어 중에 가장 기본은 version을 확인하는 것 아니겠는가? 아래 명령어를 입력해보자.

$ docker version

이제부터 도커의 명령어들을 알아보자


Container

컨테이너 조작 관련 커맨드이다. 컨테이너를 실행하거나 종료하고, 컨테이너 목록을 확인하는 등 컨테이너를 다루기 위해 사용하는 커맨드이다.

컨테이너는 각각의 독립된 환경을 의미한다.

Summary 😎

하위 커맨드내용생략 가능 여부주요옵션
start컨테이너 실행O-i
stop컨테이너 정지OX
create도커 이미지로부터 컨테이너를 생성O--name 컨테이너명
-e
-p 포트
-v 볼륨명
run도커 이미지를 내려받고(docker image pull)
컨테이너를 생성해(docker create)
컨테이너를 실행(docker start)하는 삼합체이다.
O[create 옵션]
--net
-d
-i
-t
rm정지 상태의 컨테이너를 삭제O-f -v
exec실행 중인 컨테이너 속에서 프로그램을 실행O-i -t
ls컨테이너 목록 실행*1-a
cp도커 컨테이너와 도커 호스트 간에 파일을 복사OX
commit도커 컨테이너를 이미지로 변환OX

*1 생략형은 docker ps


Example 😍

🤞 docker start: 도커 컨테이너 시작

$ docker start [컨테이너명]

🤞 docker stop: 도커 컨테이너 정지

$ docker stop [컨테이너명]

🤞 docker create: 도커 이미지로 컨테이너를 생성

$ docker create --name [컨테이너명] -e [환경변수 목록] -p [호스트포트:포트] -v 볼륨명 or [호스트경로:경로]

🤞 docker run: 도커 레지스트리나 로컬에서 도커 이미지를 받아와서(docker pull) 컨테이너를 생성(docker create)하고 실행(docker start)

$ docker run --name [컨테이너명] -e [환경변수 목록]
	-p [호스트포트:포트] -v [볼륨명 | 호스트경로:경로] --net=[네트워크명] -d -it
	--restart [no|on-failure|unless-stopped|always] [이미지명]

# 예시
$ docker run --name web -p 80:80 -d httpd

🤞 docker rm: 컨테이너를 삭제한다.

$ docker rm -f -v [컨테이너명]
$ docker rm -f web

🤞 docker exec: 컨테이너에 접속

$ docker exec [컨테이너명]
$ docker exec --it web bash

🤞 docker cp: 호스트와 컨테이너간 파일을 주고 받는다.

$ docker cp [호스트 파일경로] [컨테이너명]:[컨테이너 내부 경로]
$ docker cp index.html web:/usr/local/apache2/htdocs/

🤞 docker commit: 현재 컨테이너를 이미지로 저장한다.

$ docker commit [컨테이너명] [이미지명:태그명]
$ docker commit web web:0.0.1

Image

도커 이미지를 내려받거나 검색하는 등 이미지와 관련된 기능을 실행하는 커맨드다.

도커의 이미지는 컨테이너를 구성하는 뼈대(bone)이다. 일반적으로 OS를 설치할 때 OS 이미지 파일(iso)이 필요한 것과 유사하다고 볼수 있다.

Summary 😎

하위 커맨드내용생략 가능 여부주요옵션
pull도커 허브 등의 리포지토리에서 이미지를 내려받음OX
rm도커 이미지 삭제*2X
ls내려 받은 이미지의 목록을 출력*3X
buildDockerfile로 부터 도커 이미지 생성O-t

*2 생략형은 docker rmi

*3 생략형은 docker images


Examples 😍

🤞 docker pull

$ docker image pull [이미지명: 태그명]
$ docker pull [이미지명:태그명]

$ docker pull httpd
$ docker pull ubuntu:18.04

🤞 docker image rm, docker rmi

$ docker image rm [이미지명: 태그명]
$ docker rmi [이미지명:태그명]

$ docker rmi httpd

🤞 docker image ls, docker images

$ docker image ls
$ docker images

🤞 docker build
Dockerfile이 있는 폴더의 상위폴더에서 이 명령을 수행한다. Dockerfile이 있는 폴더의 내용은 빌드시 컨테이너에 같이 포함된다.

$ docker image build [Dockerfile이 있는 폴더]
$ docker build [Dockerfile이 있는 폴더]

$ docker build ./docker_folder

Volume

볼륨 생성, 목록 확인, 삭제 등 볼륨과 관련된 기능을 실행하는 커맨드다.

볼륨이란, 컨테이너에 마운트 가능한 스토리지를 의미한다. 여기서의 볼륨 명령어는 도커 엔진이 관리하는 논리적 영역의 스토리지이다.

실제, 컨테이너를 생성할때는 -v 옵션을 통해 볼륨에 마운트할 수 있는데, 이때 이 볼륨에는 도커 엔진이 관리하는 영역의 볼륨이나 실제 호스트 경로를 마운트할 수 있다.

Topic. Volume을 지정하는 이유

볼륨을 지정하는 이유는 컨테이너는 쉽게 생성되고 폐기되기 때문에, 데이터를 안전하게 관리하기 위해서 사용된다.

docker rm 명령어 사용하여 컨테이너 폐기시, 옵션 -v를 넣지 않으면 볼륨은 사라지지 않는다.

Summary 😎

하위 커맨드내용생략 가능 여부주요옵션
create볼륨 생성X--name
inspect볼륨의 상세 정보를 출력XX
ls볼륨 모두 출력X-a
prune현재 마운트되지않은 볼륨 모두 삭제XX
rm지정한 볼륨 삭제XX

Examples 😍

🤞 docker volume create [볼륨명]: 볼륨을 생성한다.

$ docker volume create web_vol

🤞 docker volume ls: 볼륨 목록을 출력한다

$ docker volume ls
# 실행 결과
DRIVER    VOLUME NAME
local     web_vol

🤞 docker volume inspect [볼륨명]: 볼륨의 상세정보를 확인한다.

$ docker volume inspect web_vol
# 실행 결과
[
    {
        "CreatedAt": "2023-02-07T09:26:07+09:00",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/web_vol/_data",
        "Name": "web_vol",
        "Options": {},
        "Scope": "local"
    }
]

🤞 docker volume rm [볼륨명]: 지정한 볼륨을 삭제한다.

$ docker volume rm web_vol
web_vol

$ docker volume ls
DRIVER    VOLUME NAME

🤞 docker volume prune: 컨테이너마운트되지 않은 볼륨을 모두 삭제한다.

$ docker volume prune
# 실행 결과
WARNING! This will remove all local volumes not used by at least one container.
Are you sure you want to continue? [y/N] y
Deleted Volumes:
web_vol

Total reclaimed space: 0B

Network

도커 네트워크의 생성, 삭제 컨테이너의 네트워크 접속 및 접속 해제 등 도커 네트워크와 관련된 기능을 실행하는 커맨드다.

관리할 수 있는 영역(create, rm, ls 등)의 도커 네트워크도커 엔진이 관리하는 일종의 컨테이너의 묶음, 즉 논리적 네트워크이라고 할 수 있겠다.

Summary 😎

하위 커맨드내용생략 가능 여부주요옵션
connect컨테이너를 도커 네트워크에 연결XX
disconnect컨테이너의 도커 네트워크 연결을 해제XX
create도커 네트워크 생성XX
inspect도커 네트워크의 상세 정보를 출력XX
ls도커 네트워크 목록 출력XX
prune현재 컨테이너가 접속하지 않은 네트워크 모두 삭제XX
rm지정한 도커 네트워크 삭제XX

Examples 😍

🤞 docker network ls: 네트워크 목록을 검색한다.

$ docker network ls
# 실행 결과
NETWORK ID     NAME      DRIVER    SCOPE
a398b520e819   bridge    bridge    local
1ba123abbb61   host      host      local
eed17555d205   none      null      local

🤞 docker network create [네트워크명]: 네트워크 추가.
docker network 를 생성하면 bridge 형태로 네트워크(컨테이너 간 결합)에 연결된다.

$ docker network create program_net
$ docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
a398b520e819   bridge    bridge    local
1ba123abbb61   host      host      local
eed17555d205   none      null      local
067141e89138   program_net   bridge    local

🤞 docker network rm [네트워크명]: 네트워크 삭제.

$ docker network rm program_net

🤞 docker network inspect [네트워크명]: 네트워크 상세정보 출력.

$ docker network inspect program_net
# 실행 결과
[
    {
        "Name": "program_net",
        "Id": "814675051bc831da182d443aa9c4b9b4786e585d8ff555eb9d353c50db703810",
        "Created": "2023-02-07T11:34:51.37797693+09:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.19.0.0/16",
                    "Gateway": "172.19.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]

🤞 docker network prune: 사용하지 않는 네트워크 모두 삭제.

$ docker network prune
# 실행 결과
WARNING! This will remove all custom networks not used by at least one container.
Are you sure you want to continue? [y/N] y
Deleted Networks:
program_net

Docker Default Network

Docker는 기본적으로 3개네트워크를 지원합니다 .

1) 없음 (None)

이 모드 는 컨테이너 에 대한 IP를 구성 하지 않으며 다른 컨테이너뿐만 아니라 외부 네트워크에 대한 액세스 권한도 없습니다 . 루프백 주소가 있으며 배치 작업을 실행하는 데 사용할 수 있습니다.

$ docker run -it --network=none ubuntu:14.04 /bin/bash
$ ifconfig

lo		Link encap:Local Loopback  
		inet addr:127.0.0.1  Mask:255.0.0.0
		UP LOOPBACK RUNNING  MTU:65536  Metric:1
		RX packets:0 errors:0 dropped:0 overruns:0 frame:0
		TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
		collisions:0 txqueuelen:0 
		RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)


$ docker inspect 66308c6686be | grep -i ipaddr
		"SecondaryIPAddresses": null,
		"IPAddress": "",
        "IPAddress": "",

2) 호스트 (Host)

이 모드에서 컨테이너는 호스트네트워크 스택공유하고 호스트의 모든 인터페이스를 컨테이너에서 사용할 수 있습니다 . 컨테이너와 호스트는 호스트명IP 구성 등이 일치합니다.

호스트 및 없음 모드에서는 직접 구성되지 않지만 기본 브리지 네트워크를 구성하고 고유한 사용자 정의 브리지 네트워크를 만들 수 있습니다.

3) 브리지 (Bridge)

호스트 시스템의 다른 인터페이스와 컨테이너 간 연결을 가능하게 하는 Docker 기본 네트워킹 모드 입니다.

브리지 모드에서는 다른 컨테이너에 대한 액세스가 가능합니다.


단독으로 쓰이는 커맨드

상위 커맨드 없이 단독으로 쓰이는 특수한 커맨드이다. 주로 도커 허브와 관련된 명령어이다.


단독 커맨드내용주요옵션
login도커 레지스트리에 로그인-u -p
logout도커 레지스트리에 로그아웃x
search도커 레지스트리 검색x
version도커 엔진 및 명령행 도구의 버전을 출력x


3. Jump to docker

Installation in Ubuntu

linux에서 Docker 설정은 (Windows/macOS랑 달리) 매우 매우 간단하다. Install command를 통해 도커를 설치하기만 하면 된다.

# Docker 설치
$ sudo apt install docker.io

# 권한 부여 (sudo 없이 도커 명령어 가능)
$ chmod 666 /var/run/docker.sock

Simple Example 💘

웹 서버 container 만들기를 실습한다. 나는 이 실습을 통해 도커를 한방에 이해했다.

http://localhost:3000 으로 동작하는 간단한 Container 를 만든다

# docker container 생성 및 실행
$ docker run [--name container_이름] [-d] [-p 호스트_포트:포트] {컨테이너_이미지명}
$ docker run --name web -d -p 3000:80 httpd

# 현재 실행 중인 Container 목록 확인
$ docker ps [-a]

# 결과
CONTAINER ID   IMAGE          COMMAND              CREATED          STATUS          PORTS                               NAMES
3f4c242bde74   httpd          "httpd-foreground"   11 minutes ago   Up 11 minutes   0.0.0.0:80->80/tcp, :::80->80/tcp   web

이제 해당 브라우저에서 3000번으로 접속한다.


💎 Reference

  • "그림과 실습으로 배우는 도커 & 쿠버네티스", 오가사와리 시게타카 지음, 심효섭 옮김, 위키북스

💎 마치며

이번 포스팅에서는 도커의 개념과 명령어, 간단한 실습을 해보았습니다. 다음 포스팅에서는 도커 컨테이너 관리에 대해 포스팅 해보겠습니다.


덧붙여, 도커를 공부하면서 여러가지 생각이 들었습니다.

  • 이렇게 좋은 도커를 왜 안쓰지? (왜 안써왔지?)
  • 그림과 실습으로 배우는 도커 & 쿠버네티스 이 책은 정말 최고의 자습서이다.
    백날 서칭한것 보다 책 한권 읽는게 원리파악에 훨씬 많은 도움이 된다
  • 생각 외로 도커는 러닝커브가 낮은거 같다. (정말 내 기준일수도?)

나는 이렇다. (내기준)

  • 리눅스에 대해 간단히 이해하고 명령어를 사용할줄 알며
  • CLI 환경의 명령어가 익숙하며 (명령어에 대한 거부감이 없다) - ex) git 커맨드
  • 서버에 대한 이해가 있다 (실제 서비스되는 웹 서버를 구성해본 적이 있다)
profile
Java, Spring 기반 풀스택 개발자의 개발 블로그입니다.

0개의 댓글