인프라/Docker

[Docker] 협업 방식 정리(2) 가상화 + docker + dockerfile + docker compose + docker network + dockerhub

Razelo 2023. 2. 16. 23:21

오늘은 docker, dockerfile, docker compose, docker network에 대해서 알아보기로 한다. 

 

협업에서 혹은 신입 개발자로 일하게 된다면 반드시 docker 혹은 가상화 기술에 대해 알고 있어야 한다. 

 

그냥 업무 숙달의 일환이라고 생각하고 간단하게 살펴보자. 


도커 공식문서: https://docs.docker.com/get-started/overview/


가상화 기술이란?

https://velog.io/@palza4dev/Docker%EC%99%80-%EA%B0%80%EC%83%81%ED%99%94-%EA%B8%B0%EC%88%A0

https://spidyweb.tistory.com/71

https://nomad-programmer.tistory.com/282

 

  • 가상화는 물리적 하드웨어 자원을 논리적인 리소스로 제공하는 기술임. 

 

호스트 OS형 

  • 물리적인 하드웨어 자원 위에 OS를 설치해서 그 위에 가상화 소프트웨어와 Virtual Machine을 움직임. 
  • 호스트 Machine과 VM간의 OS가 다를 수 있음. (VMware, Virtual Box)

 

하이퍼바이저 가상화

  • 물리적 서버의 OS위에 여러 다른 독립적인 OS가 가상으로 돌아감.
  • 호스트 OS를 필요로 하지 않는 타입의 가상화 방식임.
  • 소프트웨어를 물리적인 하드웨어 자원 위에 직접 동작하게 함. 

 

장점

  • 물리적 서버 리소스를 효율적으로 사용 

 

단점

  • 기술적으로 너무 무거움. 
  • 독립적인 OS를 사용해서 부팅시간도 길고 리소스를 많이 먹음 
  • base os와 가상화 os 사이에서 커널 시스템 호출을 연결시켜주는 에뮬레이션 layer 가 필요함. 

 

컨테이너 가상화 

OS 커널 위의 유저 공간에서 실행함. 

독립적인 운영체제 가상화가 아니라 독립적인 유터 스페이스 가상화 

 

장점

  • 하이퍼바이저 가상화보다 가볍고 빠름
  • 에뮬레이터가 필요없음
  • 그냥 일반적인 시스템 API 인터페이스를 사용
  • 도커 이미지만 있으면 어디서든 가능
  • MSA와 CI/CD 랑 찰떡궁합

 

단점

  • 보안적인 면에서 하이퍼바이저보다 약함.
  • 운영체제가 전혀 다른 호스트에서는 실행 불가 

  • 도커는 한 컨테이너 당 하나의 application이나 프로세스를 실행하는 것을 권함.
  • MSA의 철학과 맞추기 위함임. 
  • 도커 컨테이너는 도커 이미지를 실행시키는 가상화 공간이다.
  • 도커 컨테이너는 하나 혹은 그 이상의 프로세스를 실행시킬 수 있지만 하나의 프로세스만 실행하는 것이 권장된다. (위에서 말한 것과 같은 이유임.)
  • Docker compose 와 Swarm 은 여러 도커 컨테이너들로 이뤄진 스택이나 클러스터를 관리하는 서비스임. 
  • Virtual Machine은 Physical hardware를 추상화해서 동작함.
  • 도커의 컨테이너 구조는 Application layer에서 종속되는 패키지 코드를 추상화해서 동작함.
  • Host OS위에서 Docker가 동작해서 여러 개의 App형태로 동작하는 것임. 

 

Docker란?

도커: 컨테이너 기반의 오픈소스 가상화 플랫폼

개발자: 솔로목 하익스 (2013년 발표, Go로 개발) 

 

  • 도커는 서비스를 운용하는데 필요한 실행환경, 라이브러리, 소프트웨어, 시스템 도구, 코드 등을 컨테이너라는 표준화된 단위로 추상화함.
  • 이렇게 만든 컨테이너는 컴퓨팅 환경에 구애받지 않고 서비스가 실행될 수 있게 함. 
  • 서비스 관리자는 도커라이징된 컨테이너가 요구하는 런타임, 라이브러리, 코드를 전혀 알 필요없음.
  • 컨테이너를 어딘가에서 가져와서 서비스를 운영할 컴퓨팅 환경에서 실행하기만 하면 됨. 
  • 실행된 서비스는 컴퓨팅 환경과 독립된 가상의 환경에서 실행되고 일관된 결과를 보장함. 
  • 전통적인 서버 관리 방식은 밑바닥부터 수작업으로 모든 걸 세팅해야함. -> 너무 귀찮죠? 
  • 도커는 OS 환경설정, 언어, 라이브러리, 시스템 도구 등이 설치된 환경을 그대로 이미지로 빌드할 수 있음.
  • 이미지는 Dockerfile을 통해 만든다. 
  • 도커는 높은 확장성과 이식성을 갖음.
  • 도커가 설치된 환경이면 어디서든 컨테이너를 실행 가능함. 

 

 

  • 오른쪽의 하이퍼바이저는 virtual box나 vm ware같은 가상 머신을 생성하고 실행하는 프로세스.
  • 하이퍼바이저는 하드웨어를 에뮬레이션하여 하나의 컴퓨터에서 다수의 운영체제를 운영할 수 있게 해주는 소프트웨어임.
  • 에퓰레이션이란 하드웨어 리소스의 동작을 소프트웨어로 대신하는 가상화 방식을 말함.  
  • 하이퍼바이저 자체를 실행하는 측을 호스트 운영체제 (Host OS) 라고 함.
  • 하이퍼바이저가 구동하는 가상화된 OS 를 게스트 운영체제 (Guest OS) 라고 함.
  • 게스트는 호스트로부터 일정량의 리소스를 할당을 받아 구동됨.
  • 운영체제 자체를 가상화하여 실행하는 특징으로 도커에 비해 상대적으로 무거움.
  • 호스트 운영체제와 게스트 운영체제의 기능 중복으로 인해 약 10 ~ 20% 의 오버헤드 (Overhead) 를 갖는다고 함.

 

 

  • 도커와 같은 컨테이너 기반 가상화 플랫폼은 게스트 운영체제 없이 프로세스를 격리하는 방식임.
  • 위 특징 때문에 호스트 운영체제의 모든 기능과 리소스를 컨테이너간 공유함.
  • 운영체제 위에 또 다른 운영체제를 구동하지 않아도 되고 리소스도 공유해서 사용하기에 오버헤드는 3 ~ 5% 이내.
  • 운영체제를 별도로 가상화 하지 않으므로 이미지 파일의 용량도 하이퍼바이저에 비해 낮음. (장점)

 

docker --version  (도커 설치되었는지 확인)

 

  • 도커 컨테이너는 Kernel 데이터를 갖고 있지 않음  
  • 다만 컨테이너가 필요로 하는 Kernel 은 Host OS 의 것을 그대로 사용하고, Kernel 외의 데이터만을 패키징하여 컨테이너가 가지고 있음.
  • Ubuntu 와 CentOS 의 차이점만을 컨테이너에 패키징되어 담고 있는 개념임.
  • Ubuntu와 CentOS 는 서로 다른 리눅스 배포판이지만 같은 Linux Kernel 을 사용하기에 이것이 가능함. 

 

  • Docker 는 Linux 환경에서만 네이티브로 동작함.
  • Linux 이외의 환경에서 도커를 사용할때에는 도커 자체가 OS 에서 지원하는 가상화 환경에서 구동됨. 
  • 가상화 기술로 Mac은 xhyve, Windows 는 Hyper-V 를 사용하여 별도의 Linux 환경을 만들 수 있음.
  • Docker의 핵심인 Docker Engine은 이 가상화 환경의 Linux 위에서 돌아간다고 함. 
  • 컨테이너가 삭제되면 데이터도 함께 삭제됨. 
  • 같은 이미지로부터 여러 컨테이너가 생성 가능함.
  • 컨테이너가 삭제되도 이미지는 그대로 남아있음.
  • 도커 이미지는 컨테이너를 실행하기 위한 모든 정보/ 의존성 등을 가지고 있기 때문에 용량이 수백메가에 이름. 
  • 도커 이미지 관리는 URL 방식으로 관리되어 태그를 붙일 수 있다. 

 

명령어 소개 

docker run

docker run <옵션> <이미지 이름:태그> <명령어> <인자>

run은 도커 이미지를 다운받고 컨테이너를 실행하는 명령어다.

-d 컨테이너를 백그라운드에서 실행 (Detached Mode)
-p 호스트 포트와 컨테이너 포트를 바인드한다. 
-v 컨테이너 내부의 디렉토리를 호스트로 마운트(연결)한다. 
-e 컨테이너에서 사용되는 환경변수를 설정한다. 
--name 컨테이너의 이름을 설정한다. 
--rm 컨테이너가 종료될 경우 컨테이너 자체를 삭제한다. 
-it 터미널 입력을 위한 옵션, -i옵션과 -t옵션은 주로 함께 쓰인다. 
-w WORKDIR를 설정한다. 

 

docker ps

현재 실행되고 있는 컨테이너를 확인한다. 

docker ps <옵션>

-a 옵션을 붙이면 Stop 상태의 컨테이너도 볼 수 있다.

 

docker stop

실행중인 컨테이너를 중지한다.

docker stop <옵션> <컨테이너 이름> <컨테이너 이름> ... 

 

docker rm

컨테이너를 제거한다.

docker rm <옵션> <컨테이너 이름> <컨테이너 이름> ... 

 

docker logs

컨테이너에 기록된 로그를 확인할 수 있다. 

docker logs <옵션> <컨테이너 이름>

-f 옵션을 사용하면 로그를 일회성으로 보여주고 끝내지 않고 기다리고 새롭게 발생한 로그도 출력해준다.  

 

docker images

현재 설치된 이미지 리스트를 출력한다.

 docker images <옵션> <레포지토리 이름>

레포지토리를 넘겨주면 특정 레포지토리의 이미지만 필터링해서 볼 수 있다.

 

docker rmi 

현재 설치된 이미지를 제거한다. 

docker rmi <옵션> <이미지 이름> <이미지 이름> ... 

 

docker pull 

이미지를 도커 레지스트리로부터 다운로드한다.

run 명령을 사용할 때 대상 이미지가 설치되지 않은 이미지일 경우 자동으로 pull해준다.

docker pull <옵션> <이미지 이름:태그>

 

Volume 옵션

Volume을 사용하면 로컬 경로에 존재하는 모든 파일들을 도커 컨테이너 내부에서 사용할 수 있다.

docker run <다른 옵션들> -v 참조할경로(로컬):참조하는 경로(컨테이너 내부) <이미지 식별자>

 

Dockerfile이란?

https://ttl-blog.tistory.com/761

도커 이미지 빌드하기 

  • 주로 다른 사람이 빌드해 놓은 이미지를 다운로드 받아서 사용함.
  • 개발자가 직접 도커 이미지를 직접 빌드할 수 있음.

npm init && npm install express를 통해 node js서버를 만들어보자 .server.js라는 파일에 간단한 웹서버를 하나 만드는 ;식으로 진행해보자.  

다 만들었으면 파일을 빌드해본다. 

 

  • 이미지를 빌드하려면 dockerfile을 작성해야함. 
  • dockerfile은 도커 이미지를 빌드하기 위한 스크립트 파일. 
  • 도커는 dockerfile을 읽고 순차적으로 명령을 실행해서 이미지를 빌드함. 

 

# 사용할 이미지 입력
FROM node:16.13.2

# 작업디렉토리 설정
WORKDIR /usr/src/app

# 앱 의존성 설치
COPY package*.json ./

# 빌드 도중에 실행할 명령어다. 
RUN npm install

# 앱 소스 추가
COPY ./server.js ./server.js

# 해당 호트를 노출시킨다. 
EXPOSE 8080

# 빌드 완료 후 실행할 명령어임. 
CMD [ "node", "server.js" ]

 

  • FROM에 있는 이미지를 베이스로 해서 스크립트가 순차적으로 실행되어 새로운 이미지가 빌드됨.
  • WORKDIR을 통해서 컨테이너의 작업 디렉토리를 설정 가능.
  • 모든 명령이 WORKDIR 경로를 기준으로 실행됨. (마치 리눅스의 cd <디렉토리명>과 비슷한 개념이라고 보자.) 

 

  • COPY를 통해서 패키지 관련 파일을 복사함.
  • RUN 명령을 통해서 npm install을 직접 실행한다. (이미지 만드는 도중에 실행하는 거다).
  • COPY 명령을 한번 더 사용해서 현재 디렉토리의 server.js를 우리가 만들려는 도커 이미지로 복사함. 
  • EXPOSE를 통해서 외부로 8080포트를 노출함.
  • CMD로 컨테이너가 실행된 직후 실행할 명령를 작성함. 
  • RUN은 이미지 빌드 단계에서 실행하는 명령어고 CMD는 컨테이너가 실행된 이후에 실행될 명령을 정의함.  
  • Dockerfile은 파일이라서 Git으로 관리가 가능하기에 이미지 변화 히스토리가 추적 가능하다. (장점)

 

아래 명령어를 통해 빌드해보자. 

 

docker build -t node-app ./ 

(./는 현재 경로라는 뜻인데 즉 지금 여기에 있는 dockerfile로 빌드하자는 뜻이다.)

-t node-app은 이미지의 이름을 설정하는 옵션이고, ./는 Dockerfile의 경로를 나타낸다. 

 

이후 아래 명령어를 따른다. 

docker images (우리가 만든 이미지가 있는지 확인할 수 있다.)

docker run -p 3000:8080 node-app (도커 컨테이너 실행)

 

도커 이미지의 레이어 구조 

  • 도커 이미지는 여러 개의 Layer가 겹겹히 쌓여있는 구조로 되어있음.

 

 

 

docker inspect wordpress (inspect 명령은 low level에서 컨테이너 혹은 이미지의 정보를 가져오는 명령)

 

  • 도커를 통해 내려받은 이미지를 구성하는 레이어는 모두 읽기 전용임. 

 

 

  • 도커 이미지는 Dockerfile의 FROM에 명시한 베이스 이미지 위에 또 다른 레이어가 얹혀져서 빌드되는 개념. 

 

이미지 순환 과정

 

새로운 이미지 만들기

docker pull ubuntu 

docker run --name my-ubuntu -it ubuntu bash 

root@121g13rf153452:/# apt update -y && install git -y              (git을 새로 설치해주자.)

root@121g13rf153452:/# exit                                                          (다운 받았으면 나오자.)

docker commit my-ubuntu razelo:ubuntu-git          (docker commit <container name> <repository:new image name>)

이후 docker images로 새로운 이미지가 추가된 지 확인 

위에서 commit 이란 해당 이미지의 수정 사항을 반영해서 새로운 이미지로 만드는 개념이다. 그래서 두번재 인자로 수정할 이름을 주는 개념이다. 

 

nodejs까지 설치된 ubuntu-git 이미지를 생성

docker run -it --name ubuntu-nodejs razelo:ubuntu-git

root@12g5114y3thwerf:/# apt update && apt install -y nodejs

docker commit ubuntu-nodejs razelo:ubuntu-nodejs

 

위 방식을 통해 nodejs 까지 설치된 이미지를 만들 수 있다. 그리고 중요한건 이 모든 과정을 Dockerfile을 통해 한 방에 할 수 있다. 

 

아래처럼 dockerfile을 작성한다. 

 

FROM ubuntu
RUN apt update 
RUN apt install -y git
RUN apt install -y nodejs

도커 파일을 실행해서 이미지로 빌드할 수도 있다. 

docker build [options] <repository:new image name> <dockerfile_path>

 

docker build -t razelo:ubuntu-git-nodejs . (마지막의 . 은 현재 디렉토리에서 Dockerfile을 찾으란 소리다.)

 

Dockerfile 명령어

LABEL

= 형식으로 메타 데이터를 넣음. 저자, 버전, 설명, 작성일자 등을 키로 하고 오른쪽에 설명을 value로 잡는다. 

LABEL version="1.0.0"

 

ENTRYPOINT

도커파일로 이미지를 만들고 컨테이너를 docker run으로 생성, 실행하면서 명령문을 같이 적으면 기존 이미지에 있는 CMD 명령이 터미널 명령으로 덮어씌워진다. 그런데 이미지에 ENTRYPOINT 항목이 있으면 docker run으로 다른 명령을 실행해도 ENTRYPOINT의 명령어에는 영향을 끼치지 못하고 ENTRYPOINT 명령 뒤에 쭉 인자로 붙는다. 즉 주입되는 명령어 방어하는 느낌이라고 보면 됨. 

ENTRYPOINT ["/bin/sh"]

 

EXPOSE

도커 컨테이너의 특정 포트를 외부에 오픈함. 

 

WORKDIR

이미지 내에서 특정 폴더로 이동하기 위해서 쓰는 명령(리눅스의 cd같은 개념이라고 보면 됨.)

 

docker build --tag <원하는 이미지명> .

docker build --tag <원하는 이미지 명> -f <dockerfile명> .

 

-f는 dockerfile의 이름이 다른 이름일 경우 사용함. 

 

ADD (auto-extraction)

복사하려는 대상 파일이 압축 파일(tar, tar.gz)일때 해당 파일의 압축을 해제해서 복사함. 

ADD는 파일을 이미지에 추가함. 

Remote-URL

wget 등을 통해서 원격지의 파일을 복사대상으로 지정 가능. 

ADD <복사할 파일 경로> <이미지에서 파일이 위치할 경로>

<복사할 파일 경로>는 파일 뿐만 아니라 디렉터리도 가능함. 디렉터리로 하면 그 안의 모든 파일을 복사함. 와일드 카드를 써서 특정 파일만 복사 가능 (ADD *.txt /root/)
또한 <복사할 파일 경로> 는 인터넷에 있는 파일의 URL로도 설정 가능함.

<이미지에서 파일이 위치할 경로>는 항상 절대 경로로 설정해야함. 마지막에 / 로 끝나면 디렉터리가 생성되고 파일은 그 아래에 복사됨.

 

COPY

host 환경의 파일 또는 디렉토리를 대상 컨테이너 이미지 안으로 복사함. 

 

ADD vs COPY

  • ADD와 COPY는 특정 위치에서 docker 이미지로 파일을 복사하는 기능을 수행함. 
  • COPY는 로컬 파일 또는 디렉토리를 컨테이너에 복사하는 기능만 지원함. 
  • ADD도 해당 기능을 지원하지만 또 다른 기능이 있음. 
  • 로컬 파일 또는 디렉토리 대신 URL을 쓸 수 있음. 

(로컬에 있는 압축 파일을 Docker 이미지의 특정 디렉토리에 추출하려는 경우에 또는 원격지의 파일을 Docker이미지로 복사하려는 경우 ADD를 사용하고 단순히 로컬 파일 또는 디렉토리를 docker 이미지로 복사하려는 경우에는 COPY를 사용하는게 일반적임.)

- ADD는 외부 URL 및 tar 파일에서도 파일을 추가할 수 있다는 점이 다르다. 

- ADD를 사용하는 것은 그다지 권장되지 않는다고 한다. 

 

MAINTAINER(deprecated)

이미지를 생성한 개발자의 정보를 나타낸다. 다만 현재는 거의 쓰이지 않는다. 대신에 LABEL을 쓰도록 하자. 

 

RUN

이미지를 만들기 위해 컨테이너 내부에서 명령어를 실행한다. 

 

CMD

컨테이너가 시작될 때마다 실행할 명령어를 설정한다. Dockerfile에서 한 번만 사용할 수 있다. 

 

EXPOSE

Dockerfile의 빌드로 생성된 이미지에서 노출할 포트를 설정한다. EXPOSE를 설정한 이미지를 컨테이너로 생성했다고 해서 반드시 이 포트가 호스트의 포트와 바인된다는 것을 보장하진 않는다고 한다. 단지 컨테이너의 해당 포트를 사용할 것임을 나타내는 명령어라고 한다. 

 

ARG 속성

여러 번 사용되는 문자열이나 숫자 등을 변수로 만들어 준다. 

ARG key=value

 

Dockerfile 예시 1 (현재 제가 사용하고 있는 설정이기도 합니다.)

FROM openjdk:11-jdk

ADD ./build/libs/findby-0.0.1-SNAPSHOT.jar findby.jar

CMD ["java", "-jar", "findby.jar"]

 

Dockerfile 예시 2

FROM ubuntu:14.04
MAINTAINER wjdrbs96
RUN apt-get update
RUN apt-get install apache2 -y
ADD test.html /var/www/html
WORKDIR /var/www/html
RUN ["/bin/bash", "-c", "echo hello >> test2.html"]
EXPOSE 80
CMD apachectl -DFOREGROUND

 

추가 명령어

docker kill <컨테이너id or 이름>

  • docker stop은 즉시 컨테이너를 중단하지 않고 현재 실행중인 단계까지는 기다리고 이후에 중지함.
  • 하지만 kill은 곧바로 중지함.

 

살펴볼 만한 명령어 모음집 

더보기

1. 특정 포트로 톰켓 실행하기

sudo docker run -d --name tc -p 80:8080 tomcat

tomcat을 pull로 받은 후 -d(백그라운드)로 실행한 후 80 port로 접속 가능하게 한다.

 

2. 컨테이너 내부 쉘 실행

sudo docker exec -it tc /bin/bash

실행된 톰켓 컨테이너로 bash를 실행해서 그 안에 접속할 수 있게 한다. 

 

3. 컨테이너 로그 확인

sudo docker logs tc 

 

4. 호스트 컨테이너 간 파일 복사

sudo docker cp [path] [to container]:[path]

- 로컬에서 컨테이너로 파일 복사 

sudo docker cp [from contatiner]:[path] [path]

- 컨테이너에서 로컬로 파일 복사 

sudo docker cp [from container]:[path] [to container]:[path]

- 컨테이너에서 컨테이너로 파일 복사 

 

5. 임시 컨테이너 생성

sudo docker run -d -p 80:8080 --rm --name tc tomcat

-  --rm 컨테이너 생성 후 종료하면 컨테이너를 삭제 

 

6. 도커 수행중인 컨테이너 정지/삭제

docker ps -a 

도커 컨테이너 조회

docker ps -a -q 

도커 컨테이너 ID만 조회

docker stop `docker ps -a -q`

도커 컨테이너 모두 종료 

docker rm `docker ps -a -q`

도커 컨테이너 모두 삭제

 

7. 도커 환경 정리 커맨드 

docker container prune 

중지된 모든 컨테이너를 삭제 

docker image prune 

이름 없는 모든 이미지 삭제 

docker network prune 

사용되지 않는 도커 네트워크를 모두 삭제 

docker volume prune 

도커 컨테이너에서 사용하지 않는 모든 도커 볼륨 삭제 

docker system prune -a

위의 세 항목 모두 삭제 

 

8. 빌드

docker build -t example .

. -> 현재 경로에서 빌드 수행하자. 

 

추가적인 내용(https://popawaw.tistory.com/235)

 

임시 컨테이너란? 

k8s에서 제공되는 개념인 듯하다. 이쪽은 일단 pass 

다만 도커 선에서 가볍게 이해하고자 한다면 --rm 옵션을 통해 도커 컨테이너가 종료되면 해당 컨테이너가 자동으로 삭제되게끔 하는 옵션으로써 임시? 잠시 동안 떴다가 죽을때 사라진다는 개념에서 임시 컨테이너라고 부르는 듯 하다. k8s로 이어지는 내용이 있는 것 같으니 추후에 다시 살펴보자. 

(https://k8s-dev-ko.netlify.app/ko/docs/concepts/workloads/pods/ephemeral-containers/)

 

Docker Network (도커 컨테이너끼리 통신하기)

https://xmobile.tistory.com/m/26

https://www.daleseo.com/docker-networks/

 

도커 컨테이너는 격리된 환경에서 돌아감.

그래서 기본적으로 다른 컨테이너랑은 통신이 불가능함.

하지만 여러 개의 컨테이너를 하나의 Docker 네트워크에 연결시키면 통신이 가능해짐. 

 

네트워크 조회

docker network ls (현재 생성되어있는 docker network list임.)

네트워크 생성

docker network create findby (새로운 도커 네트워크 생성)

네트워크 상세 정보 조회 

docker network inspect findby (출력되는 내용을 보면 단지 network생성만 해줬기 때문에 Containers 항목에 아무 컨테이너도 없음을 확인할 수 있다.)

네트워크에 컨테이너 하나를 연결

docker run -it -d --name mysql mysql (컨테이너를 실행할 때 --network 옵션을 주지 않으면 기본적으로 bridge의 디폴트 네트워크에 붙는다.)

Containers항목에 추가되었는지 다시 한번 확인

docker network inspect bridge

위 mysql컨테이너를 위의 findby네트워크에 연결할 수 있다. 

docker network connect findby mysql 

findby 네트워크의 상세 정보를 확인하면 Containers항목에 mysql 컨테이너가 추가된 것을 볼 수 있음.

docker network inspect findby

네트워크에서 컨테이너 연결 해제

mysql 컨테이너를 최초 생성하면 bridge에 붙어있다. 그래서 mysql 컨테이너는 지금 bridge와 findby에 둘다 붙어있다. 그래서 mysql컨테이너는 bridge에서 떼어낼 수 있다.

docker network disconnect bridge mysql

두번째 컨테이너 연결하기 

docker run -it -d --name findby --network findby findby 

docker network inspect findby

컨테이너 간 네트워킹

docker exec mysql ping findby

(만약 여기서 command not found이슈가 발생하면 해당 포스팅 참고: https://spongeb0b.tistory.com/532)

docker exec findby ping mysql 

네트워크 제거하기 

docker network rm findby

제거할 네트워크에 실행 중인 컨테이너가 있으면 지워지지 않음. 

그러니 네트워크에 연결되서 실행 중인 모든 컨테이너를 중지 시키고 삭제하자. 

docker stop findby mysql

docker network rm findby  

 

네트워크 드라이버 종류

docker network ls 

도커는 3개의 네트워크를 이용한다.

  • bridge: 기본 네트워크 드라이버, 드라이버를 지정하지 않으면 default bridge를 사용한다.
  • host: 호스트 네트워킹을 직접 사용한다.
  • none: 모든 내트워킹을 비활성화한다. 
  • 같은 네트워크 안에 있는 컨테이너간에서만 통신이 가능함.
  • 사용자가 만든 외부 네트워크를 사용하면 컨테이너 이름으로 연결 가능함. 

 

  • 도커는 컨테이너에 내부 IP를 순차적으로 할당한다. 
  • 도커 네트워크는 실행 중인 각각의 컨테이너를 연결하는 논리적인 네트워크이다. 

 

[꿀팁] Docker사용해서 MySQL사용하기 

docker pull mysql 

docker run --name mysql -e MYSQL_ROOT_PASSWORD=<password> -d -p 3306:3306 mysql:latest

docker exec -it mysql bash

bash-4.4# mysql -u root -p

 

Docker Hub에 배포하기

  • 개발자가 다운로드하는 도커이미지는 모두 도커 레지스트리에서 받음.
  • 도커 레지스트리는 도커 이미지를 관리하는 저장소.
  • 도커 레지스트리 중 유명한건 도커에서 공식 운영하는 도커 허브.
  • 도커 허브에 개발자가 빌드한 이미지를 배포하면 누구나 이미지를 pull받을 수 있음. 
  • 도커 허브에 이미지를 배포해보자요. ㅎㅎ 
  • 도커 허브에 이미지를 배포하려면 이미지의 이름을 수정해야함.(필수는 아님)
  • 도커 허브에 이미지를 배포할 때는 이미지의 이름을 사용자명(소문자)/이미지명:태그 형태로 바꾸는게 국룰이라고 함.

 

docker tag node-app <사용자명>/node-app   (이미지 이름을 변경한다.)

docker login  (도커 허브에 로그인한다.) 

docker push <사용자명>/node-app   (도커 허브에 자신의 레포지토리에 이미지를 업로드)

docker rmi <사용자명>/node-app     (로컬에 설치된 이미지를 제거)

docker run <사용자명>/node-app      (도커 허브에 등록된 이미지를 run, 최신을 받아온다.)

 

  • node.js앱이실행되면 성공. 

 

DockerHub (https://hub.docker.com/)

도커허브에 올리기

dockerhub는 본인이 생성한 image를 docker hub을 통해서 다른 사람들과 공유할 수 있도록 해주는 곳이고 다른 사람이 생성한 이미지를 pull해서 사용할 수 있다. 또한 docker image들이 공유되는 곳이다. 

 

  1. 가입
  2. 리포지토리 생성(생성할 이미지를 올릴 곳을 만들어야겠죠?) (private은 계정 당 한 개 까지 무료다.)
  3. 터미널로 돌아온다. 

docker login       (docker image를 push하려면 login을 해야 한다.)

docker build -t <username>/<repository 이름>:<tag 명> . 

docker push <username>/<repository 이름>:<tag 명>

이후 도커 허브에 접속해보면 잘 올라간 것을 확인할 수 있다. 

 

도커허브에서 받아오기 

기본에 있던 이미지와 컨테이너를 삭제한 상태

docker login 

docker pull <repository 이름>:<tag 명>

이후 docker images 로 확인한다. 

이후 잘 들어왔으면 run 한다. 

 

Docker compose란?

https://learn.microsoft.com/ko-kr/dotnet/architecture/microservices/multi-container-microservice-net-applications/multi-container-applications-docker-compose

 

  • 컨테이너를 실행할 때마다 모든 옵션을 넣어주고 환경변수를 입력해주는 것이 귀찮은 작업임. 
  • 때문에 도커 컴포즈가 제공됨.
  • 도커 컴포즈는 여러 컨테이너를 모아 하나의 어플리케이션을 구성할 때 사용됨. 
  • 도커 컴포즈는 도커 데스크톱을 설치하면 기본으로 제공. 
  • 시스템 구축과 관련된 명령어를 하나의 텍스트 파일에 기재
  • 한 번에 시스템 전체를 실행하고 종료와 폐기까지 한번에 하게 해줌. 

 

docker compose vs docker file vs k8s

  • 도커 컴포즈는 docker run 명령어를 여러 개 모아놓은 개념임
  • 도커 컴포즈는 컨테이너와 주변 환경(네트워크, 볼륨 등)을 한번에 생성 할 수 있음. 
  • dockerfile script는 컨테이너가 아니라 이미지를 만들기 위한 도구임.
  • dockerfile script는 네트워크나 볼륨같은 컨테이너 주변 환경은 생성이 불가능함.
  • k8s는 도커 컨테이너를 관리하는 도구임.
  • k8s는 도커 컴포즈와 혼동하기 쉬운데 사용목적이 아예 다름,
  • docker compose로 컨테이너 관리는 불가능함. 

 

  • 도커 컴포즈는 도커 엔진과 별개의 소프트웨어임.
  • 다만 도커 컴포즈로 생성한 컨테이너를 도커 엔진으로 똑같이 관리할 수 있음. 

 

주의사항

  • 정의 파일은 한 폴더에 하나만 있을 수 있음.
  • 여러 개의 정의 파일을 사용하려면 그 개수만큼 폴더를 만들어야 함. 

 

예시 1

$ docker run --name wordpress000ex12 -dit --net=wordpress000net1 -p 8085:80 -e WORDPRESS_DB_HOST=mysql000ex11 -e WORDPRESS_DB_NAME=wordpress000db -e WORDPRESS_DB_USER=wordpress000kun -e WORDPRESS_DB_PASSWORD=wkunpass wordpress
version: "3"

 services:
   wordpress000ex12:
     depends_on:
       - mysql000ex11
     image: wordpress
     networks:
       - wordpress000net1
     ports:
       - 8080:80
     restart: always
     environment:
       WORDPRESS_DB_HOST=mysql000ex11
       WORDPRESS_DB_NAME=wordpress000db
       WORDPRESS_DB_USER=wordpress000kun
       WORDPRESS_DB_PASSWORD=wkunpas

 

docker-compose version   (설치되었는지 확인)

 

  • 도커 컴포즈 설정 파일은 YAML포맷을 사용해서 작성함. 

compose file 항목

항목 docker run 커맨드의 해당 옵션 or 인자 내용
version 도커 컴포즈의 버전 기재
services 컨테이너 정의 (컨테이너의 집합체 = 서비스)
image 이미지 인자 사용할 이미지 지정
networks --net 접속할 네트워크 지정
volumes -v, --mound 스토리지 마운트(볼륨) 설정
ports -p 포트 설정
environment -e  환경변수 설정
depends_on 없음 다른 서비스에 대한 의존관계 정의
restart 없음 컨테이너 종료 시 재시작 여부 설정
  • depends_on은 다른 서비스에 대한 의존 관계를 설정해줌.
  • 컨테이너 생성 순서나 연동 여부를 정의함.
  • a 컨테이너 정의에 depends_on: -b 라고 되어있다면 b 컨테이너를 먼저 생성하고나서 a 컨테이너를 만든다. 

 

  • -f 옵션을 통해서 compose file 경로 지정 가능 
docker-compose -f docker-compose-local.yml up

 

 

docker-compose up

옵션 내용
-d 백그라운드로 실행
--no-color 화면 출력 내용을 흑백
--no-deps 링크된 서비스를 실행하지 않음
--force-recreate 설정 또는 이미지가 변경되지 않더라도 컨테이너를 재생성
--no-create 컨테이너가 이미 존재할 경우 다시 생성하지 않음
--no-build 이미지가 없어도 이미지를 빌드하지 않음.
--build 컨테이너를 실행하기 전에 이미지를 빌드
--absort-on-container-exit 컨테이너가 하나라도 종료되면 모든 컨테이너를 종료
-t, --timeout 컨테이너를 종료할 때의 타임아웃 설정 (default = 10초)
--remove-orphans 컴포즈 파일에 정의되지 않은 서비스의 컨테이너를 삭제
--scale 컨테이너의 수를 변경

 

docker-compose down

생성 된 컨테이너와 네트워크 종료하고 삭제

옵션 내용
--rmi 삭제 시에 이미지도 삭제
-v, --volumes volumes 항목에 기재된 볼륨을 삭제 (external로 지정된 볼륨을 삭제 되지 않음)
--remove-orphans 컴포즈 파일에 정의되지 않은 서비스의 컨테이너도 삭제

 

docker-compose stop

컨테이너 종료 

 

docker compose 사용 전 단계 순서

  1. 각각의 컨테이너의 Dockerfile을 작성한다. (기존 이미지를 사용한다면 불필요함)
  2. docker-compose.yml 파일을 작성하고 독립된 컨테이너의 실행 정의를 써준다. 
  3. docker-compose up 명령어를 실행해서 컨테이너를 개시한다. 

내용 좋은 블로그 

https://engineer-mole.tistory.com/221

 

 

예시 2

version: "3"

services:
  app:
    build:
      context: ./01_FLASK_DOCKER
      dockerfile: Dockerfile
    links:
      - "db:mysqldb"
    ports:
      - "80:8080"
    container_name: appcontainer
    depends_on:
      - db
  db:
    image: mysql:5.7
    restart: always
    volumes:
      - ./mysqldata:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=dgkcoding
      - MYSQL_DATABASE=dgkdb
    ports:
      - "3306:3306"
    container_name: dbcontainer

명령어 정리

-build 

컨테이너를 기동하기 전에 build를 진행하는 경로를 기술함. 

기본적으로 ./Dockerfile을 기본 도커 파일로 사용하기에 필요하다면 build.dockerfile옵션에 도커 파일의 이름과 경로를 지정한다. images 옵션은 따로 주지 않으면 ${service}:latest 이름으로 이미지가 생성됨. 

docker image를 dockerfile 기반으로 작성한다.

context는 dockerfile이 있는 디렉토리를 의미함. 

dockerfile은 dockerfile의 파일명을 의미함. 

 

-links (docker의 run 명령의 -link의 흡사)

특정 docker container 내부에서 다른 docker container에 접속하고 싶을 때 사용.

 

 

 

예시 3

 

version: "3" # docker-compose 파일 규격 버전
services:
  mysql-db: # 컨테이너 이름
    image: mysql:5.7 # 이미지
    volumes: # -v 옵션
      - ./mysql:/var/lib/mysql
    environment: # -e 옵션
      MYSQL_ROOT_PASSWORD: wordpress
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: wordpress

 

  • version은 도커 컴포즈 파일의 규격버젼.
  • 3.x버전대를 사용한다는 뜻. 
  • services는 도커 컴포즈에서 컨테이너를 의미함.
  • 여기서는 mysql-db라고 이름을 정함. 
  • 컨테이너 이름 다음에는 우리가 docker run을 실행하며 넣어줬던 여러 옵션을 YAML 포맷으로 넣어주면 됨. 이건 내가 써주고 싶은 거에 따라 내용이 많이 추가될 수 있음. 

 

다 적어줬으면 docker-compose.yml이 있는 디렉토리에서 터미널로 아래 명령어로 해서 컨테이너를 실행한다.

 

docker-compose up 

 

위 명령어 치면 이미지를 pull하고 컨테이너가 실행됨. 

(M1 맥북 사용자는 도커 컴포즈 파일의 environment 옵션 아래에 platform: linux/x86_64 를 추가해주면 된다고 한다. 나는 문제 없던데? 암튼)

 

도커 컴포즈 장점

컨테이너가 여러 개 실행되야 하는 시스템 구성할때 깔끔하게 정리할 수 있다. 명령어가 굉장히 간단하고 직관적이어서 쉽게 배울 수 있다. 

 

예시 4

services:
  db:
    environment:
      POSTGRES_PASSWORD: postgres
      POSTGRES_USER: postgres
    image: postgres
  web:
    build:
      context: /Users/dale/temp/django-app
    command: python manage.py runserver 0:8000
    depends_on:
    - db
    ports:
    - 8000:8000/tcp
    volumes:
    - /Users/dale/temp/django-app:/web:rw

 

docker compose 알아두면 좋은 명령어

실행 docker-compose up 
백그라운드에서 실행 docker-compose up -d 
서비스 중지 docker-compose stop 
서비스 다운 docker-compose down 
서비스 다운 후 볼륨삭제 docker-compose down --volumes 
컨피그 확인하기 docker-compose config  
실행중인 서비스 컨테이너 명령어 실행하기 docker exec <서비스이름> <명령어> 
실행중인 서비스 확인하기 docker-compose ps 
서비스 로그 확인하기 docker-compose logs  
서비스 로그 지속적으로 프린트하기 docker-compose logs -f  
서비스 로그 지정해서 확인하기 docker-compose logs <서비스이름>   
서비스 로그 여러개 지정해서 확인하기 docker-compose logs <서비스이름> <서비스이름> ...   

실쟁 중인 docker container에 명령어를 실행 docker-compose exec <컨테이너명> <명령>

 

그 외 헷갈리는 개념들

docker working directory란?

이미지 안에서 어플리케이션 소스 코드를 갖고 있을 디렉토리를 생성하는 것이다.

이 디렉토리가 어플리케이션에게 working 디렉토리가 되는 개념임. 

working directory를 지정하지 않고 copy하면 다른 파일들과 함께 한 디렉토리에 저장된다. 물론 원래 이미지에 있던 파일과 이름이 같으면 덮어씌워진다. 즉 앵간하면 workdir는 써 주는 게 좋다는 뜻임. 

 

 

docker 볼륨이란?

https://devzzi.tistory.com/m/74

 

docker 마운트란? 

 

 


[부록]  Redis Cluster with docker compose 

 

레디스 클러스터란?

https://velog.io/@tngusqkr1/Redis-cluster-%EC%84%A4%EC%A0%95-1

 

레디스 클러스트 docker compose 만드는 법 

https://hwasurr.io/redis/cluster/

https://pinggoopark.tistory.com/267

https://kimdubi.github.io/cloud/docker_redis_cluster/

https://kmseop.tistory.com/236

https://velog.io/@zittoooo/docker-compose%EB%A1%9C-Redis-cluster-%EB%A7%8C%EB%93%A4%EA%B8%B0

 


도움 받은 링크는 아래와 같다. 

 

감사합니다. 

 

아래 블로그는 꼭 읽어보자. 굉장히 정리가 잘 되어있다.

 

가상화

https://velog.io/@palza4dev/Docker%EC%99%80-%EA%B0%80%EC%83%81%ED%99%94-%EA%B8%B0%EC%88%A0

https://spidyweb.tistory.com/71

https://nomad-programmer.tistory.com/282

 

Best of best

https://devocean.sk.com/blog/techBoardDetail.do?ID=163621 

https://tecoble.techcourse.co.kr/post/2022-09-20-docker-basic/

 

기타 자료들 

https://choewy.tistory.com/119

https://www.44bits.io/ko/post/building-docker-image-basic-commit-diff-and-dockerfile

https://velog.io/@tjdwns2243/dockerfile-%EB%AC%B8%EB%B2%95-%EC%9E%91%EC%84%B1%EB%B2%95

 

도커 컴포즈 커맨드 정리 

https://engineer-mole.tistory.com/259

https://velog.io/@korjsh/Docker-%EC%BB%B4%ED%8F%AC%EC%A6%88-%EA%B8%B0%EC%B4%88-%EB%B0%8F-%EB%AC%B8%EB%B2%95

https://devzzi.tistory.com/m/76

https://engineer-mole.tistory.com/221

 

 

 

도커 개념 

https://brother-big.tistory.com/2

 

도커 이미지 빌드와 이미지 기초 

https://www.44bits.io/ko/post/building-docker-image-basic-commit-diff-and-dockerfile

 

ADD & COPY

https://parkgaebung.tistory.com/44

 

도커허브에 이미지 배포 

https://soyoung-new-challenge.tistory.com/53

https://reddb.tistory.com/183

 

도커파일

https://pyrasis.com/jHLsAlwaysUpToDateDocker/Unit07/09

https://devlog-wjdrbs96.tistory.com/296

 

도커 유용한 명령어 

https://choo.oopy.io/bd00bc47-bff9-46ab-876a-31e9b290000f 

 

 

 

반응형