1. 메타데이터
이번 시간에는 이미지의 메타데이터에 대해 학습한다. 메타데이터는 데이터에 대한 데이터를 의미한다. 지난 시간에 학습한 이미지가 실제로 압축된 데이터라면, 메타데이터는 이 이미지에 대한 정보를 기술하는 데이터이다.
예를 들어 식물을 키운다고 가정해보자. 이 식물의 이름이 무엇인지, 물은 언제 주고 온도를 몇 도로 맞춰야 하는지, 시간이 지나면 금방 까먹게 된다. 그래서 화분에 이러한 정보를 라벨로 정리해서 붙인다. 이 데이터는 식물에 대한 정보를 정리한 데이터이다. 이미지도 마찬가지로 이미지의 이름이 무엇인지, 사이즈가 어떻게 되는지에 대한 정보를 저장하고 관리해야 한다. 이미지 파일 데이터에 대한 데이터, 메타데이터라고 부르는 것이다.
하나의 이미지는 실제로 압축된 파일과 이 파일의 정보가 저장되어 있는 메타데이터로 구성되어 있다. 위의 그림처럼 메타데이터 안에는 많은 정보들이 저장되는데, Nginx 이미지의 메타데이터를 표시하고 있다. 이 메타데이터를 살펴보면 이미지의 ID, RepoTags, Env, Cmd, Size 등 다양한 정보를 포함하고 있다. 이때 자세하게 살펴봐야 할 부분은 바로 Env 와 Cmd 필드이다.
2. 이미지 메타데이터 Env, Cmd
Env는 소프트웨어가 실행 시 참조할 설정 정보이다. Env는 애플리케이션이 사용하는 환경 설정 값을 의미하고 키와 값으로 구성되어 있다. 위의 그림에서 이미지의 메타데이터 안에 Env 를 살펴보면 Env: VERSION= 1.23.2
으로 =
을 기준으로 키(왼쪽)와 값(오른쪽)으로 나누어져 있는 것을 확인할 수 있다. Nginx 이미지에는 소프트웨어 버전과 Nginx 프로그램을 실행할 때 필요한 파일 경로 같은 정보가 Env 안에 저장되어 있다. 그래서 Env 값이 변경되면 Nginx 는 다른 방식으로 동작할 수 있다.
Env
정리하자면 Env 는 소프트웨어가 실행할 때 사용할 설정 정보라고 생각하면 된다. 그리고 Cmd는 이미지를 컨테이너로 실행할 때 명령어를 지정할 수 있다. 일반적으로 윈도우에서 프로그램을 실행할 때는 바탕화면에서 아이콘을 클릭하고, 리눅스에서는 일반적으로 명령어를 통해 프로그램을 실행한다. 이미지 컨테이너로 실행할 때 CMD에 있는 명령어를 통해서 어떠한 프로그램을 실행할지를 메타데이터에서 결정한다.
Cmd
지정한 Nginx 이미지의 압축 파일과 이미지의 메타 데이터를 사용해서 격리된 공간인 컨테이너가 생성된다. 이 시점에서 이제 컨테이너 안에 있는 파일 시스템과 메타데이터는 새롭게 격리되어 있는 공간이고, 이 이미지가 컨테이너로 실행될 때 Cmd 필드에 있는 nginx -g demon off
라는 명령어가 실행이 되는 것이다. 그리고 이 Nginx 같은 프로세스가 실행되면서 Env 필드에 있는 환경 설정 값을 사용할 수 있게 된다.그리고 이 메타데이터는 컨테이너를 실행할 때 새로운 값으로 덮어쓰기 할 수 있다. 이제 실습을 통해서 메타데이터를 덮어쓰기 해 보면서 메타데이터를 테스트해보자.
3. docker inspect
- docker image inspect 이미지명: 이미지의 세부 정보 조회
- docker container inspect 컨테이너명: 컨테이너의 세부 정보 조회
- docker run 이미지명 (실행명령): 컨테이너 실행 시 메타데이터의 cmd 덮어쓰기
- docker run --env KEY=VALUE 이미지명: 컨테이너 실행 시 메타데이터의 env 덮어쓰기
docker image inspect
뒤에 이미지명을 입력하면 이미지의 세부 정보 조회를 할 수 있다. 즉, 이미지의 메타데이터를 확인할 수 있다. 그리고 docker container inspect
뒤에 컨테이너의 이름을 입력하면 실행 중인 컨테이너의 메타데이터를 확인할 수 있다. 이번 실습에서는 이미지를 컨테이너로 실행하면서 이미지의 메타데이터에 있는 Cmd 와 Env 필드에 덮어쓰기를 수행한다.
먼저 Cmd 를 덮어쓰기 하려면 docker run
이미지명 옆에 덮어쓰기를 수행할 실행 명령을 입력하면 된다. 그리고 Env 필드를 덮어쓰기 할 때에는 docker run
명령의 옵션을 --env
으로 덮어쓰기 하면 된다. 줄여서 -e
으로 덮어쓰기를 할 수 있다. 이렇게 옵션 옆에 덮어쓰기를 수행할 키와 값을 제공하면 된다.
4. docker image inspect nginx
docker image inspect
뒤에 이미지명 nginx
를 입력하면 이미지 세부 정보 조회가 가능하다. 해당 메타데이터를 살펴보면 이미지의 아이디(Id
)가 출력되고, 이미지를 다운받을 때 사용하는 태그(RepoTags
)도 확인이 가능하다. 이미지가 생성된 시간(Created
)도 확인할 수 있다. 그리고 아래를 살펴보면 Config
안에 Env
필드와 Cmd
필드를 확인할 수 있다. Env
를 살펴보면 Nginx 의 버전, 패스 환경 변수의 정보를 살펴볼 수 있다.
그리고 Cmd
에는 nginx
-g
demon off
라는 명령어가 배열로 저장되어 있다. 해당 Cmd
필드는 띄어쓰기가 인식이 안 되기 때문에 띄어쓰기를 기준으로 배열로 저장되어 있는 것이다. 이 세 개의 배열 값들을 하나로 합치면 nginx -g demon off
라는 명령어가 완성된다. 이제 nginx
이미지를 컨테이너로 실행하자.
5. docker run -d --name defaultCmd nginx
docker run -d --name defaultCmd nginx
으로 nginx 이미지를 defaultCmd 이름의 컨테이너로 실행한다.
docker container inpsect defaultCmd
그리고 실행된 컨테이너의 메타데이터를 확인해 보려면 docker container inspect
이미지명인 defaultCmd
를 입력한다. 그림처럼 실행 중인 컨테이너의 메타데이터를 확인할 수 있다. Config
에서 동일한 Env
와 Cmd
를 확인할 수 있다. 여기에 있는 Env
와 Cmd
필드는 Nginx 이미지의 메타데이터를 그대로 복사해서 가져온 값이다. 다음 실습을 진행하기 전에 리눅스의 cat 명령에 대해 학습한다.
6. cat
- docker run --name customCmd nginx cat usr/share/ngnix/html/index.html: 기본 이미지의 메타데이터를 사용해 컨테이너 실행
cat 명령은 리눅스에서 제공되는 기본 명령 중 하나이다. cat 뒤에 파일이 있는 경로를 입력하면 파일의 내용을 출력할 수 있다.
이제 이미지에 있는 메타데이터에서 Nginx 프로그램을 실행하는 nginx -g demon off
라는 Cmd
필드를 덮어쓰기한다. 덮어쓰기하는 명령을 확인하기 위해서 docker run --help
를 입력하면 그림과 같이 docker run
그리고 이미지명 오른쪽에 커멘드를 확인할 수 있다. 이 커멘드 부분이 바로 Cmd
필드에 덮어쓰기할 명령어를 의미한다.
7. docker run --name customCmd nginx
docker run
명령을 사용해서 새로운 컨테이너를 실행해보자. docker run --name
뒤에 컨테이너명은customCmd
, 이미지명은 nginx
로 지정한 후에 덮어쓰기 할 명령어는 한 칸 띄운 상태에서 cat 뒤에usr/share/nginx/html/index.html
파일을 지정하면 된다. 콘솔창에 index.html
파일이 출력되는 것을 확인할 수 있고, 웹 브라우저로 Nginx 웹 사이트에 접속했을 때 브라우저에 표시되는 파일과 동일한 HTML 코드 내용을 확인할 수 있다.
어떠한 수정도 없이 Nginx 이미지를 그대로 컨테이너로 실행하면 Nginx 서버는 요청을 받았을 때 usr/share/nginx/html/index.html
폴더 안에 있는 index.html
파일을 응답해주는 것이라고 볼 수 있다. 이제 실행된 컨테이너의 메타데이터를 살펴보자.
docker container inspect customCmd
를 입력하여 결과를 살펴보면 해당 Cmd
필드의 값이 변경된 것을 확인할 수 있다. 그리고 docker ps
명령을 입력하면 처음에 실행한 defaultCmd만 확인되고 customCmd는 보이지가 않는다. 그 이유는 customCmd 컨테이너에서 실행한 cat 명령은 파일의 내용을 출력하고 종료되는 일회성 프로세스이기 때문에 Cmd 에서 지정한 cat 명령이 종료되는 순간 컨테이너도 함께 종료가 되는 것이다. customCmd 는 종료된 상태의 컨테이너이기 때문에 일반적인 docker ps 명령으로는 조회가 되지 않고, -a
옵션을 함께 작성하여 종료된 컨테이너까지 모두 확인해야 한다. -a
는 all 을 의미한다.
8. docker ps -a
customCmd 컨테이너는 Exited 라고 해서 종료된 상태인 것을 확인할 수 있다. 이 컨테이너는 이미지의 데이터를 복사해서 생성되기 때문에 실제로 컨테이너의 메타데이터를 변경한다고 해서 이미지의 메타데이터가 변경되는 것이 아니다.
docker image inspect nginx
명령을 실행하면 위의 그림처럼 Nginx 이미지 Cmd의 페이드는 동일하게 유지가 되어 있는 것을 확인할 수 있다. 따라서 변경할 수 있는 것은 이미지를 복사해오면서 실행하는 시점에 컨테이너의 메타데이터만 변경할 수 있다. 다음으로 docker run
명령과 함께 사용한 -d
옵션에 대해 학습한다.
9. docker run -d
docker run 명령과 함께 사용했었던 -d
옵션은 데몬의 약자이며 컨테이너를 백그라운드에서 실행하는 것을 의미한다. 첫 번째 Nginx 를 실행할 때는 -d
옵션을 주고, 두 번째 cat 명령을 실행할 때는 -d
옵션 없이 실행했다. 그래서 이 -d
옵션을 주지 않으면 컨테이너의 출력이 사용자의 커멘드 창과 연결된다. 그런데 cat 명령은 일회성 명령이고, 화면에 파일의 내용을 출력하고 종료되기 때문에 다시 사용자의 입력 창으로 돌아올 수 있는 것이다.
하지만 Nginx 같은 경우는 지속적으로 실행되는 데몬 프로세스이기 때문에 -d
옵션을 주지 않으면 지속적으로 화면에 로그가 출력된다. 그러면 더 이상 명령어를 실행할 수 없기 때문에 추가로 명령어를 실행하기 위해서는 -d
옵션을 주어서 백그라운드에서 실행되도록 설정해야 한다. -d
옵션을 주면 커맨드 라인에는 실행된 컨테이너의 아이디(Id
)만 출력된다.
그래서 -d
옵션은 지속적으로 실행되는 소프트웨어를 사용할 경우에는 대부분 추가하는 것이 좋다. 하지만 cat 명령처럼 결과를 바로 확인해야 하거나 실시간으로 소프트웨어가 출력하는 로그를 보고 싶을 때는 -d
옵션 없이 사용하면 된다.
이제 실습한 내용을 정리하자. defaultCmd는 어떠한 설정 없이 Nginx 이미지를 그대로 컨테이너로 실행했고, 이미지의 메타데이터 안에 있는 nginx -g demon off
명령어가 컨테이너의 메타데이터로 복사되었다. 컨테이너는 Nginx 프로세스를 실행했고, nginx 웹 서버는 지속적으로 실행되는 데몬 프로세스이기 때문에 -d
옵션을 주었다. 두 번째로 customCmd 컨테이너를 실행하면서 Cmd를 cat 명령으로 수정했다. 이 과정에서 이미지의 메타데이터는 그대로 유지되지만, 실행되는 컨테이너의 메타데이터가 새로운 값으로 덮어쓰기 되었다. 그래서 customCmd 컨테이너는 웹 서버가 아니라 파일의 내용을 출력하고 종료되었다.
cat 명령은 일회성 명령이기 때문에 -d option
을 넣지 않고 컨테이너가 출력하는 내용을 직접 확인했다. 그러면 이제 다음으로 Env 필드에 대해 학습한다. 두 번째로 실행할 컨테이너는 이미지의 메타데이터에 지정된 환경 변수를 덮어쓰기 한다.
10. env
이번 실습을 진행하기 위해서 간단한 실습용 애플리케이션인 Env Node Color App이라는 애플리케이션을 사용한다. Env Node Color App는 사용자에게 특정 색상의 웹페이지를 응답한다. 비즈니스 로직이 있는 경우에는 단순히 특정 파일을 응답해주는 웹 서버만으로는 요구사항을 충족시킬 수 없다. 그래서 이 Env Node Color App 앱은 Node.js라는 자바스크립트 기반으로 개발된 백엔드 애플리케이션이다. 먼저 이미지의 메타데이터를 확인하기 위해서 이미지를 다운받아 보자.
11. docker pull devwikirepo/envnodecolorapp
이미지는 docker pull
명령을 사용해서 다운받을 수 있다. 다운받을 이미지의 이름은 devwikirepo/envnodecolorapp
으로 이미지가 다운로드 되는 것을 콘솔창에서 확인할 수 있다. 다운로드가 완료되면 docker image inspect devwikirepo
안에 envnodecolorapp
을 입력해서 이 이미지의 메타데이터를 확인한다.
12. docker image insepect devwikirepo/envnodecolorapp
Env 피드의 내용을 살펴보면 color 라는 키에 red 라는 값을 가지고 있는 것을 확인할 수 있다. 그리고 Node.js 애플리케이션을 실행하는 npm start
라는 명령이 Cmd 필드에 지정되어 있는 것을 확인할 수 있다. 이제 다운받은 이미지를 컨테이너로 실행하자.
13. docker run -d -p 8080:3000 --name defaultColorApp devwikirepo/envnodecolorapp
docker run -d -p 8080:3000 --name defaultColorApp devwikirepo/envnodecolorapp
으로 컨테이너가 실행되는 것을 확인할 수 있다. 해당 이미지의 Env
필드를 가져오기 때문에 color
라는 키의 값이 필드로 되어 있을 것이다. 그럼 이제 두 번째 컨테이너를 실행하는데, 이때 -d
, -p
를 8081, 3000으로 설정하고 --name
은 blueColorApp으로 지정한다. 그리고 여기에서 추가적으로 -env
옵션을 주고, COLOR
는 blue
으로 입력한다. COLOR는 대문자, blue는 소문자로 입력한다.
14. docker run -d -p 8081:3000 --name blueColorApp --env COLOR=blue devwikirepo/envnodecolorapp
docker run -d -p 8081:3000 --name blueColorApp --env COLOR=blue devwikirepo/envnodecolorapp
으로 두번째 컨테이너도 실행했다. 그리고 blueColorApp 컨테이너의 메타데이터를 확인하기 위해 docker container inspect blueColorApp
명령을 수행한다.
15. docker container inspect blueColorApp
localhost:8080으로 크롬의 시크릿 모드로 실행 중인 defaultColorApp에 접속한다. defaultColorApp에는 Env 필드의 COLOR 값이 red로 설정되어 있기 때문에 글씨 색깔이 빨간색으로 표시되는 것을 확인할 수 있고, localhost:8081에서는 blueColorApp을 확인할 수 있다. blueColorApp은 마찬가지로 Env 필드의 COLOR 값이 blue로 설정되어 있기 때문에 글씨 색깔이 파란색으로 표시되는 것을 확인할 수 있다.
이번 실습에서는 환경 변수값을 읽어서 환경 변수별로 다른 색을 출력하는 Env Node Color App을 사용했다. 첫 번째로 defaultColorApp 컨테이너는 어떠한 변수도 지정하지 않았기 떄문에 이미지에 지정되어 있는 변수인 red를 그대로 사용했다. 그리고 두 번째 blueColorApp 컨테이너는 환경 변수의 COLOR 값을 blue로 덮어쓰기 했다. 이제 실습에 사용된 컨테이너를 모두 제거한다.
지금까지 실습에 사용된 컨테이너를 확인하기 위해 docker ps -a
명령으로 삭제해야 될 컨테이너를 확인한다. 그리고 docker rm -f defaultCmd customCmd defaultColorApp, blueColorApp
으로 모든 컨테이너를 삭제한다.
16. 이미지 메타데이터 정리
이미지는 실제 압축 파일과 메타데이터로 구성되어 있다. 이미지를 컨테이너로 실행하면 이미지의 파일과 메타데이터가 컨테이너로 생생되고 메타데이터의 Env에 정의되어 있는 환경 변수가 사용된다. 그리고 Cmd 에 정의되어 있는 명령어로 프로그램을 실행하는 것을 확인할 수 있다. 그리고 이 Env 와 Cmd는 실행할 때 덮어쓰기가 가능하기 때문에 이 내용을 수정해서 같은 이미지에서 다른 결과를 확인도 할 수 있었다.
첫 번째 실습에서는 Cmd, 두 번째 실습에서는 Env 내용을 덮어쓰기 수행을 했다. 이 실습을 통해서 컨테이너를 실행할 때 메타데이터의 내용을 수정할 수도 있고 같은 이미지도 전혀 다른 역할을 수행할 수 있는 컨테이너로 만들 수 있다는 것을 학습했다. 이렇게 실행 시에 메타데이터를 수정하는 것이 사실 일반적인 방법이 아니다. 보통 이미지를 디버깅할 때 주로 사용하는 방법이다.
하지만 이렇게 직접 메타데이터를 수정해 보면서 메타데이터의 개념을 충분히 이해하셨을 거라고 생각한다. 이번 시간에는 이미지와 컨테이너의 메타데이터에 대해 살펴봤다. 그리고 run 명령을 실행할 때 -d
옵션에 대해 정리했다. 실습에서 본 것처럼 컨테이너는 실행 상태인 running 과 종료 상태인 existed 가 있으며 그 이외에도 여러 가지 상태가 존재하고 있다. 다음 시간에는 컨테이너가 가질 수 있는 컨테이너의 생명 주기에 대해 학습한다.
'도커 > 개발자를 위한 쉬운 도커' 카테고리의 다른 글
3.1 도커(Docker) 이미지와 레지스트리: 이미지 레지스트리 (0) | 2024.06.19 |
---|---|
2.4 도커(Docker) 이미지와 컨테이너: 컨테이너의 라이프사이클(Lifecycle) (1) | 2024.06.19 |
2.2 도커(Docker) 이미지와 컨테이너: 이미지와 컨테이너 (0) | 2024.05.30 |
2.1 도커(Docker) 이미지와 컨테이너: 이미지 (0) | 2024.05.30 |
1.3 도커(Docker) 가상화 기술: 컨테이너 실행 (0) | 2024.05.30 |