본문 바로가기
클라우드 공부

1. 도커와 컨테이너

by tlgusdl03 2024. 7. 19.
docker images
docker image ls

서론 

팀 프로젝트를 진행하거나, 포트폴리오를 만들 때 빼놓을 수 없는 것이 배포와 운영일 것이다. 또한 최근 클라우드가 각광 받으며 관련된 도커나, 쿠버네티스 기술에 관심을 갖는 사람들도 늘었다. 많은 사람들이 사용하는 만큼 그 이유가 있을 것이다. 공부를 시작하기에 앞서 이 기술들이 왜 쓰이는지부터 알아보자

중요한 것은 추상화, 격리

컨테이너는 실행에 필요한 모든 파일을 포함한 전체 실행(runtime) 환경에서 애플리케이션을 패키징하고 격리할 수 있는 기술입니다. 이를 통해 전체 기능을 유지하면서 컨테이너화된 애플리케이션을 환경(개발, 테스트, 프로덕션 환경 등) 간에 쉽게 이동할 수 있습니다. 컨테이너는 IT 보안의 중요한 부분이기도 합니다. 컨테이너 파이프라인에 보안을 구축하고 인프라를 보호하여 컨테이너의 안정성, 확장성, 신뢰성을 보장할 수 있습니다. 또한 일관된 행동과 기능으로 퍼블릭, 프라이빗, 하이브리드 클라우드 환경과 데이터센터(또는 온프레미스) 간에 컨테이너화된 애플리케이션을 손쉽게 이동할 수 있습니다.
 

컨테이너 보안(Container Security)의 개념, 기능, 장단점, 방법

컨테이너 보안이란 애플리케이션, 기반 인프라, 소프트웨어 공급 네트워크, 런타임 등 컨테이너의 모든 요소가 실행되도록 보안 툴 및 정책을 구현하는 과정입니다.

www.redhat.com

컨테이너 보안이란 애플리케이션, 기반 인프라, 소프트웨어 공급 네트워크, 런타임 등 컨테이너의 모든 요소가 안전하게 실행되도록 보안 도구 및 정책을 구현하는 과정을 말한다. 레드햇 홈페이지에서도 언급하듯, 컨테이너는 애플리케이션을 패키징하고 격리한다. 이는 개발자가 초기 설정과 배포에 소요되는 시간을 줄이고, 개발에 더 많은 시간을 투자할 수 있도록 해준다. 잦은 변화에 빠르게 대응할 수 있기에 컨테이너 기술이 각광받는 이유이다.

이를 통해 우리는 컨테이너 기술의 중요성과 그 사용 이유를 명확히 이해할 수 있다. 특히 서비스 개수 만큼 서버의 개수가 늘어나 수백 수천개의 상황이라면 배포와 운영에서의 효율성, 보안 강화, 그리고 다양한 환경 간의 유연한 이동성을 제공하는 이 기술들은 현대 개발 환경에서 필수라는 것을 더욱 이해할 수 있을 것이다.

 

VM vs Container

기존 virtual machine은 Hypervisor위 머신 별로 별도의 OS를 포함하고 있어서 무겁고, 느리다. 반면, Container는 격리된 상태에서 Linux의 커널을 공유하여 사용하기에 별도의 OS가 없고, 빠르게 배포할 수 있고 가볍다.

Docker

  • 도커에서 핵심이 되는 것은 Docker daemon이다. 사용자가 docker 명령어를 사용하여 api를 사용하면 Docker daemon이 이를 처리한다.
  • Dockerfile에 작성한 명령어들은 이미지로 빌드가 되어 Registry에 저장된다.
  • 이미지는 컨테이너를 만드는 Template이다.

Docker CLI

docker search [OPTIONS] <keyword>

Registry에서 이미지를 검색한다.

docker pull [OPTIONS] REPOSITORY[:TAG|@DIGEST]

Registry에서 이미지를 다운로드 받는다. DIGEST 값을 사용하여 정확한 버전의 이미지를 검색할 수 있으며, tag를 사용하여서도 검색할 수 있다. REPOSITORY만 입력한 경우 자동으로 latest를 다운로드 받는다.

docker images [OPTIONS] [REPOSITORY[:TAG]]

이미지 목록을 조회 할 수 있다. REPOSITORY만 명시한 경우 해당 이름만 가진 이미지만 검색한다.

docker rmi [OPTIONS] IMAGE [IMAGE...]

한개 이상의 명시된 이미지를 삭제한다.

docker image prune [OPTIONS]

모든 dangling 이미지를 삭제한다. dangling 이미지란, Repository가 none으로 표기되는 이미지를 의미한다. 일반적으로 dangling 이미지는 동일한 이름(Name & tag)를 가진 다른 이미지를 생성하는 경우, Multi-Stage 빌드 중 중간이미지로 생성된다.

docker inspect [OPTIONS] NAME|ID [NAME|ID...]

이미지의 자세한 정보를 출력한다.

root@8ab92b491e04:/code (eks:default)# docker inspect tlgusdl03/fortunek8s
[
    {
        "Id": "sha256:2de760906e5f889b848ae18ae310df0451f48dd6e17bb78937eda796b1789324",
        "RepoTags": [
            "tlgusdl03/fortunek8s:latest",
            "tlgusld03/fortunek8s:latest"
        ],
        "RepoDigests": [
            "tlgusdl03/fortunek8s@sha256:9655a5837bc147ac0b554f70c6ad4a2fcde3dc0638e65ea1a427b85b4d696762"
        ],
        "Parent": "",
        "Comment": "buildkit.dockerfile.v0",
        "Created": "2024-07-18T01:26:19.591960778Z",
        "ContainerConfig": {
            "Hostname": "",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": null,
            "Cmd": null,
            "Image": "",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": null
        },
        "DockerVersion": "",
        "Author": "",
        "Config": {
            "Hostname": "",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": null,
            "Image": "",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": [
                "/bin/sh",
                "-c",
                "/bin/fortuneloop.sh"
            ],
            "OnBuild": null,
            "Labels": {
                "org.opencontainers.image.ref.name": "ubuntu",
                "org.opencontainers.image.version": "24.04"
            }
        },
        "Architecture": "amd64",
        "Os": "linux",
        "Size": 119436304,
        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/x0wtovjx3g70a5prm0t081gc2/diff:/var/lib/docker/overlay2/vbz7beipmwg6ze4nevy98mxsn/diff:/var/lib/docker/overlay2/4a0eee8e4a9200ef4888fd1240d3fdaaeca58bc61298362105ab0e6cd730fab8/diff",
                "MergedDir": "/var/lib/docker/overlay2/zgtelj2sdekvhfi100194yz2v/merged",
                "UpperDir": "/var/lib/docker/overlay2/zgtelj2sdekvhfi100194yz2v/diff",
                "WorkDir": "/var/lib/docker/overlay2/zgtelj2sdekvhfi100194yz2v/work"
            },
            "Name": "overlay2"
        },
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:a30a5965a4f7d9d5ff76a46eb8939f58e95be844de1ac4a4b452d5d31158fdea",
                "sha256:fd0da0897a09e46a4f3aef40bf27dd867f4f71f6ccdd5c0b7a2513b2ea982924",
                "sha256:02d6da2fb15a37bc9563bf677741e2c0d50bc02c42823c0764a7a8f7b77bb720",
                "sha256:1a6b4964972e54f1527d8d193697d64bb3f28b12fcd22c0f1e20cb5062e1c624"
            ]
        },
        "Metadata": {
            "LastTagTime": "2024-07-18T01:45:14.930905494Z"
        },
        "Container": ""
    }
]

이미지에 있어서 가장 중요한 레이어를 확인할 수 있다.

docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

이미지를 통해 컨테이너를 실행한다.

Option Short Description
--name   컨테이너의 이름을 지정함
--detach -d 컨테이너를 백그라운드에서 실행함
--env -e 환경변수를 설정함
--env-file   환경 변수를 저장한 파일을 설정함, 여러개의 환경변수를 설정할 때 사용함
--expose   포트 또는 포트 범위를 노출함, 같은 네트워크의 컨테이너의 통신이 가능하게 함
--publish -p 컨테이너의 포트를 공개함, 호스트 또는 외부와의 통신이 가능하게 함
--rm   컨테이너가 종료되면 자동으로 삭제함
--interactive -i STDIN을 활성화 함
--tty -t pseudo-TTY를 활성화 함
--volume -v 볼륨을 설정함
docker ps [OPTIONS]

동작중인 컨테이너의 목록을 볼 수 있다. -a 옵션과 함께하면, 종료된 컨테이너의 목록도 볼 수 있다.

docker logs [OPTIONS] <NAME_OR_ID>

컨테이너의 로그를 확인할 수 있다.

docker exec -it [OPTIONS] <ID_OR_NAME> /bin/bash|sh|...

현재 실행중인 컨테이너에서 새로운 명령어를 실행한다. 메인 프로세스가 실행되는 동안에만 명령어를 실행할 수 있고, exec로 실행된 명령은 컨테이너 재실행시 실행되지 않는다. 또한 일부 이미지로 생성된 컨테이너는 bash, sh과 같은 shell이 없을 수 있다.

# 종료
docker stop <NAME_OR_ID>
# 시작
docker start <NAME_OR_ID>
# 중지
docker pause <NAME_OR_ID>
# 재실행
docker unpause <NAME_OR_ID>

start와 stop의 경우 재실행 할 시 Dockerfile을 통해 실행되지 않은 프로세스는 재실행되지 않는다. pause와 unpause를 통해 중지된 경우에는 모든 프로세스가 재실행된다.

docker rm [OPTIONS] CONTAINER [CONTAINER...]

컨테이너를 삭제한다. --force, -f 옵션을 통해 실행중인 컨테이너를 강제로 삭제할 수 있고, --volumes, -v 옵션을 통해 컨테이너의 annonymous volumes도 함께 삭제할 수 있다.

docker build [OPTIONS] PATH | URL | - [-f <PATH_TO_FILE>]

docker buildx build [OPTIONS] PATH | URL | - [-f <PATH_TO_FILE>]

Dockerfile을 이미지로 빌드한다. -f를 통해 dockerfile의 위치와 이름을 지정할 수 있고 지정하지 않았다면 같은 디렉토리의 Dockerfile을 찾는 것이 디폴트이다. -t 옵션을 통해 이미지의 이름과 Tag를 설정할 수 있다.

docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]

이미지의 이름과 태그를 변경할 수 있다.

docker push [OPTIONS] NAME[:TAG]

이미지를 Docker hub 또는 별도의 registry에 업로드 할 수 있다. 이를 위해 사전에 docker login을 통해 registry에 인증해야 한다.