DevOps

Docker 정복하기 실습편

devdubu 2023. 3. 6. 14:22

Docker 실습 주의 사항

Docker에 대한 강의를 들어보면 보통 혼란이 많이 찾아온다.
나도 그랬다.
Docker를 분명히 처음 배울때는

docker container start 어쩌구...

이런 식으로 하다가

갑자기 어느순간부터 CLI가 길어지더니, Dockerfile을 다루는 법을 또 배우더니 Docker-compose는 뭐니 하면서 배우게 된다.


그러다가 때려치게 된다. ㅎ


내가 그랬다가 어떻게든 이해하겠다는 의지로 책 2,3권 씩 읽다가 겨우 마음에 평화가 찾아왔다.

그래서 독자들에게는 조금 더 쉽게 정리해서(내 기준이지만,,,) docker의 사용법을 정리해보려고 한다.

Docker CLI

기본적으로 Docker를 다룰 때 쓰는 방법이다.


한개 정도의 Container를 다룰 때는 의미가 있는 방법이다.

 

그리고 Log를 확인 할 때나, docker로 접근 할 때 든지에는 많이 사용하지만, 처음에 실습을 위해서 사용하는 명령어가 많지, 그 이후에는 많이 사용하는 방식은 아니다.

docker run --name nexus -d -p 5050:5050 -p 8081:8081 -v /nexus-data:/nexus-data -u root sonatype/nexus3

이유인 즉슨, Shell이기 때문에, 기록을 따로 하지 않으면 남지 않으며, 위 처럼 가독성이 매우 떨어진다는 단점을 가지고 있다.

Dockerfile

많이들 오해 할 수 있는 부분이 Docker CLI == Dockerfile 이라고 오해를 한다.
하지만, 전혀 아니다.

Dockerfile의 같은 경우에는 해당 Container의 이미지를 만드는데 필요한 구성요소(설치해야할 패키지 목록, Container에 필요한 CMD 등)을 넣어놓는 것이다.


즉, container를 좀 더 구체적으로 쓰기 위해서(위의 휘발성의 특징을 갖기 때문에, 휘발 되면 안되는 데이터의 같은 경우를 저장하기 위해서)

 

해당 Dockerfile을 만들고 나면, Docker를 실행하기 위해서는 결국 Docker CLI를 이용해서 Docker를 실행합니다.
그렇기 때문에 Docker CLI와 Dockerfile은 범주가 다른 것이라고 이해하셔야 합니다.

예시

FROM node:16-alpine

WORKDIR /app

COPY package*.json ./

RUN npm install

COPY . .

EXPOSE 3000

CMD [ "npm", "start" ]

결국 위와 같이 docker image를 생성하고, 실행하는 것은 위의 docker run 명령어를 통해서 생성해야한다는 점 입니다.

Docker-compose

docker-compose까지 와야지 비로소 Docker CLI를 대체할 수 있습니다.

Docker CLI를 자세히 보시게 된다면, 옵션이 다양합니다.


-p -> Port, -v -> Volume, -u -> user

 

등등 실 서버를 구성하기 위해서는 구성해야하는 요소들이 꽤 많이 잇습니다.

(Volume은 휘발성을 없애기 위한 요소로 추후에 자세히 설명해드리겠습니다.)

 

물론 CLI에 docker-compose up -d 라는 명령어를 써야하긴 하지만, 위의 CLI처럼 복잡한 명령어는 아니기에 Docker CLI를 대체할 수 있다고 할 수 있습니다.


Container에 대해서 외부적인 것들과 network에 대한 모든 설정은 이 docker-compose.yaml에서 제어합니다.
아래는 저희 동아리에서 사용하는 Node 서버와 MariaDB 서버에 대한 docker-compose 파일의 예시입니다.

version: '1.0.0'
services:

    node-server:
        container_name: back_node
        restart:
            always
        image:
            back
        build: ./backend
        environment:
            TZ: Asia/Seoul
        ports:
        - "3000:3000"
        networks:
            - import_network
        depends_on:
            - mariadb

    mariadb:
        container_name: mariadb
        image: mariadb:latest
        restart: always
        # 환경에 따라 변경
        ports:
            - "3306"
        volumes:
            - ./db/mysql.sql:/docker-entrypoint-initdb.d/mysql.sql
        # DB 데이터 저장 디렉터리
            - ./data:/var/lib/mysql

        # 설정 파일 저장될 위치
            - ./config:/etc/mysql/conf.d

        environment:
            MYSQL_DATABAS: import
        # 정의하지 않으면 실행 시, 에러가 발생합니다.
        MYSQL_ROOT_PASSWORD: import1015
        # 컨테이너 내의 시스템 타임존을 우리나라에 맞게 설정합니다.
        TZ: Asia/Seoul
        command:
        # 위 명령어를 사용하지 않으면, 일부 설정이 latin으로 설정됩니다.
            - --character-set-server=utf8mb4
            - --collation-server=utf8mb4_unicode_ci
        networks:
            - import_network
    networks:
        import_network:
        driver: bridge

본격적인 실습

이라고 하면서 아직도 이론이 안끝났습니다 ㅎ

그 전에 docker가 어떤 식으로 작동이 되는지를 알아야지 의미가 있습니다.

DockerHub

Docker에서는 이미지를 관리한다고 합니다.
여기서 이미지란, 윈도우 설치시에 iso 파일처럼 보통 인프라에서는 주요 os를 image화 하여 저장한다고 합니다.


Image가 뭔데 그래서 라고 생각하시는 분들은 아래의 사이트에서 확인하시길 바랍니다

https://www.alibabacloud.co.kr/video-20/

 

Snapshot과 Image를 활용한 클라우드 서버 백업 | 알리바바클라우드 국내 유일 공식 총판

알리바바 클라우드에서 제공하는 서버백업의 종류엔 Snapshop과 Image가 있다. 그렇다면 그 둘의 차이점은 무엇이며 각자 어떤 상황해서 사용해야 할까? -알리바바 클라우드 Snapshot 알리바바 클라

www.alibabacloud.co.kr

사실상 백업을 위해서 사용되는 기술이라고 생각하면 됩니다.

 

그렇기 때문에, 만약 새로운 프로젝트를 시작할 때는 퓨어(순수)한 이미지를 다운을 받고, 해당 이미지를 가지고 가공하면 더 빠르고 쉽게 프로젝트 진행이 잘 될 겁니다.

 

그래서 만든 개념이 Docker에서는 image pull, push입니다.

어디서 많이 들어본 개념일 것입니다.

아시는 분들은 아시다싶이, Git에서 해당 개념이 있죠.


docker image도 똑같은 개념으로 사용됩니다.

즉, git과 똑같이 저희는 항상 git에서 local pc에 코드가 없다면 clone을 할겁니다.


docker도 마찬가지로, local pc에 docker image가 없다면, clone 할겁니다.

이러한 방식은 git과 비슷하다보니, git을 이해하신다면 docker의 방식도 이해하시기 편할겁니다.

 

그리고 docker의 이미지는 layer로 구성되어있지만, 이는 어려운 개념이므로 docker 심화편에서 자세히 얘기하겠습니다.

찐 실습

서두가 너무 길었네요 이제 진짜로 docker 실습을 진행해보려고 합니다.


우선 docker가 설치 되어있고, 작동이 되어있는지 확인해야합니다.

작동이 되었는지 확인이 된다면,


이제부터 터미널을 켜주시길 바랍니다.

우선 실습으로는 간단하게 Nginx를 실행해보려고 합니다.

# docker의 버전 확인 -> 버전 확인으로 docker가 정상적으로 명령어가 먹는지 확인 가능
docker --version

docker run -p 80:80 nginx

위의 명령어를 치게 된다면, 아래의 사진과 같이 다운로드 후에 Nginx가 실행되는 것을 알 수 있습니다.


확인은 localhost 으로 접속하면 접속 되는 것을 확인 할 수 있다.
그렇다면 실제 container가 떠있는 것을 확인하는 방법은 아래의 명령어로 확인이 가능합니다.

# 현재 docker container 중 실행 중인 것에 대한 상태를 띄워주는 
docker ps

# 중지된 것도 포함하여, 모든 container에 대한 상태를 띄워주는 명령어
docker ps -a

위의 Docker 명령어 처럼, 자주 쓰이는 명령어는

  • container
  • network
  • logs
  • exec
    등등이 있습니다.

이외의 명령어를 사용하실 분들은 아래 Docker 공식 Docs에 자세히 설명되어 있다보니, 그 쪽에서 살펴보시길 바랍니다.
https://docs.docker.com/engine/reference/commandline/cli/

container

docker container [option] [container name]

위와 같은 명령어로 사용이 가능합니다.

docker container start

  • ==정지 중인 컨테이너를 시작할 때== 사용합니다.
  • 컨테이너에 할당된 컨테이너 식별자를 지정하여 컨테이너를 시작합니다.

docker container stop

  • ==실행중인 컨테이너를 정지==할 때 사용합니다.

docker container rm

  • 컨테이너를 삭제할 때 사용합니다.

docker container run

docker container run [옵션] 이미지명[:태그명][인수]
옵션
옵션 설명
--attach, -a 표준 입력(STDIN), 표준 출력(STDOUT), 표준 오류 출력(STDERR)에 Attach한다.
--cidfile 컨테이너 ID를 파일로 출력한다.
--detach -d 컨테이너를 생성하고 백그라운드에서 실행한다.
--interactive, -i 컨테이너의 표준 입력을 연다.
--tty, -t 단말기 디바이스를 사용한다.

위와 같은 옵션을 주로 사용할 수 있다고 하지만, 거의 대부분은 -d 옵션을 많이 사용합니다.

좋은건 알겠는데...글쎄...뭔가 부족해..

하지만, 어플리케이션을 실행하기에는 뭔가 기능이 부족합니다.


아시다 싶이, 우리가 흔히 사용하는 웹 프레임워크 중에서 예를 들면 NodeJS, Spring은 저희가 IDE에서 Start 버튼을 누르거나, 혹은 npm start라는 명령어를 통해서 실행합니다.

 

그 과정에서 단순히 run을 하는 것이 아닌, Dependance도 다운 받아야하며, package도 다운 받아야하죠..
그럼 이 과정은 어떤 식으로 해결해야할까요?

Dockerfile

이제서야 비로소 Dockerfile의 존재가 부각 됩니다.


dockerfile은 docker-cli로 해결하지 못한 container image 의 부분을 해결 할 수 있게 도와주는 보조적인 역할입니다.

 

즉, Dockerfile이 존재하는 순간부터는 Dockerfile -> image이고,
docker-cli

  • image build(이미지 빌드)
  • image start(빌드 된 이미지를 실행하는 역할)
    위의 두가지 역할을 수행하는데 사용됩니다.

아래의 코드로 예를 들자면,

FROM node:16-alpine

WORKDIR /app


COPY package*.json ./

RUN npm install



COPY . .

EXPOSE 3000

CMD [ "npm", "start" ]
  • 위 예시를 가지고 왔습니다.
    맨 위부터 차례대로 해석하자면,
    명령어 설명
    FROM 어떤 이미지를 사용할건지(Docker Hub에서 가져오는 베이스 이미지)
    WORKDIR 기본적으로 사용할 디렉토리 (있으면 사용, 없으면 생성)
    COPY .(현 Dockerfile기준 디렉토리) .(Container의 기준 디렉토리-> WORKDIR)
    EXPOSE 그냥 3000번 포트 써요~ 표시해주는 것
    CMD Container에서 사용할 명령어를 작성하는 란

우선 위의 dockerfile에 나오는 정도까지만, 명령어를 표현해보았습니다.
더 많은 명령어를 알고 싶으시면, 아래의 링크로 자세히 살펴보시길 바랍니다.
https://docs.docker.com/engine/reference/builder/

 

Dockerfile reference

 

docs.docker.com

Docker-compose

dockerfile을 통해서 Docker Image를 완성했다면, 이제부터는 Docker-Compose를 통해서 각각의 docker Image들을 Container화 하여서 서버를 연결해주는 작업이 필요합니다.

우선 아래의 예시를 들겠습니다.

version: '1.0.0'
services:

    node-server:
        container_name: back_node
        restart:
            always
        image:
            back
        build: ./backend
        environment:
            TZ: Asia/Seoul
        ports:
        - "3000:3000"
        networks:
            - import_network
        depends_on:
            - mariadb

    mariadb:
        container_name: mariadb
        image: mariadb:latest
        restart: always
        # 환경에 따라 변경
        ports:
            - "3306"
        volumes:
            - ./db/mysql.sql:/docker-entrypoint-initdb.d/mysql.sql
        # DB 데이터 저장 디렉터리
            - ./data:/var/lib/mysql

        # 설정 파일 저장될 위치
            - ./config:/etc/mysql/conf.d

        environment:
            MYSQL_DATABAS: import
        # 정의하지 않으면 실행 시, 에러가 발생합니다.
        MYSQL_ROOT_PASSWORD: import1015
        # 컨테이너 내의 시스템 타임존을 우리나라에 맞게 설정합니다.
        TZ: Asia/Seoul
        command:
        # 위 명령어를 사용하지 않으면, 일부 설정이 latin으로 설정됩니다.
            - --character-set-server=utf8mb4
            - --collation-server=utf8mb4_unicode_ci
        networks:
            - import_network
    networks:
        import_network:
        driver: bridge

위의 코드는 YAML이라는 문법 코드 입니다.
주로 container_name, build, ports, networks 등등은 꼭 있는 것을 볼 수 있습니다.

위에서 Docker CLI로 진행했을 때, 주로 사용했던 container 이름, port 번호, network 종류 등등을 Docker-compose에서 설정 할 수 있습니다.

더 자세한 문법을 보고 싶으시면 아래의 사이트에서 확인해보시길 바랍니다.
https://docs.docker.com/compose/features-uses/

 

Key features and use cases

 

docs.docker.com

 

'DevOps' 카테고리의 다른 글

Docker 정복 하기 이론 편  (0) 2023.02.27