https://docs.docker.com/reference/cli/docker/container/

위 페이지에 나와있는 명령어를 중요도 순으로 실습하고 이를 정리하는게 본 포스트의 목적이다.
먼저 실습 전 할 일로 runapp.js라는 파일과 Dockfile 파일을 코드작성을 진행하자
1) runapp.js
// Node.js의 내장 HTTP 모듈을 가져옵니다.
// 이 모듈을 통해 HTTP 서버를 생성함
const http = require('http');
// http 서버 객체를 생성하고 6060포트로 입력되는 요청은 수신하게 설정한다.
// 서버 객체는 클래스 형태니까 이걸 'server'라는 변수에 인스턴스화 시킴
const port = process.env.PORT || 6060;
const server = http.createServer().listen(port);
console.log(`Server listening on port ${port}`);
// 서버 객체에는 `request`라는 이벤트 리스너 메서드가 있다.
// `request` 이벤트는 클라이언트가 HTTP 요청을 보낼 때 발생하며,
// 콜백 함수로 요청(req)과 응답(res) 객체를 전달받는다.
server.on('request', (req, res) => {
console.log("Your req arrived.");
res.write("HostName : " + (process.env.HOSTNAME || "Unknown Host") + "\n");
res.end();
});
//여기서 env는 환경변수 내 hostname 정보를 참조해서 출력하는데
// 도커 run에서 `-h node-run` 정보가 여기에 들어감
// 서버 객체의 `connection`이벤트는 서버와 클라이언트가 연결될 때 활성화됨
// 이때 콜백함수가 연결된 소캣 객체(socket)을 전달받음
server.on('connection', (socket) => {
console.log("Your Connected.");
});
위 코드는 Node.js 플랫폼에서 구동되는 언어체계 같은것이나
필자는 음.. 잘 모른다(첨 봣는데스..)
일단 주석은 내가 이해할 수준으로 작성했다...
2) Dockerfile

생성하는 도커파일은 위 도커 허브의 node 이미지를 바탕으로 커스텀 도커파일을 생덩한다.
# 도커 허브에 올라와 있는 node.js 23버전의 경량 Alpine 리눅스 이미지를 사용
FROM node:23-alpine3.20
# `tini`와 `curl` 패키지를 설치
# - `tini`: 컨테이너의 PID 1 프로세스 문제를 해결하기 위한 init 시스템
# - `curl`: 네트워크 요청을 테스트하거나 디버깅에 유용
RUN apk add --no-cache tini curl
WORKDIR /app
COPY runapp.js .
# 환경 변수를 사용해 기본 포트를 설정 (기본값: 6060)
ENV PORT=6060
# 컨테이너 외부에 노출할 포트를 환경 변수로 설정
EXPOSE ${PORT}
# 컨테이너가 시작되면 `tini`를 실행
# `tini`는 PID 1 문제를 해결하고 신호 처리를 안정적으로 수행
ENTRYPOINT ["/sbin/tini", "--"]
# 컨테이너 실행 시 node.js 어플리케이션 실행
CMD ["node", "runapp.js"]
여기서 tini는 처음보는데 컨테이너 환경에서 사용하는 경량 init(초기화) 시스템이란다.
PID 1번 프로세스를 잡는것 같은데
음.. 잘 모르겟지만 경량 컨테이너의 안정적인 사용에 필요하다니 넣자..
두개의 파일을 만들었으면 빌드를 진행하자

docker build -t noderun:1.1 .
위 명령어로 빌드가 되면 도커 이미지가 생성된다.
여기서 -t는 해당 이미지의 태그를 지정하는 것이고,
마지막에 .은 현재 이 명령어가 실행되는 디렉토리를 빌드 컨텍스트로 사용한다는 것이다.
빌드를 완료한 뒤에는 CLI로 빌딩된 이미지 리스트를 확인하자.
이때 OS별로 명령어가 살짝 차이가 난다.
docker images | findstr noderun # 윈도우 버전
docker images | grep noderun # 우분투 버전

좀 더 자세하게 빌드한 이미지 정보를 확인은 아래의 명령어로 수행한다.
docker image history noderun:1.0
을 기입하면

위 사진처럼 확인이 가능하며, 우선 당장은 가장 중요한 데이터는 역시
EXPOSE map[6060/tcp:{}] 이다.
이제 빌드한 이미지를 컨테에너화 + 등록 + 실행을 수행하자
docker run -itd -p 6060:6060 --name=node-run -h node-run noderun:1.1

컨테이너 등록이 잘 되었는지 확인 명령어는 아래와 같다.
docker ps | findstr node-run # 윈도우 버전
docker ps | grep node-run # 우분투 버전

접속 가능한 포트가 생성된거니
아래의 명령어로 실 접속이 가능한지 확인하자
curl localhost:6060

위 사진처럼 나오면 정상이다.
우선 여기까지 수행 후 명령어에 대한 설명을 이어나가겠다.
| 옵션 | 설명 |
|---|---|
-i, --interactive | 대화식 모드 열기 |
-t | TTY(단말 디바이스) 할당 |
-d, --detach=true | 백그라운드에서 컨테이너 실행하고 컨테이너 ID 등록 |
--name | 실행되는 컨테이너에 이름 부여 (미 지정 시 자동으로 부여됨: 딕셔너리 워드 랜덤 선택) |
--rm | 컨테이너 종료 시 자동으로 컨테이너 제거 |
--restart | 컨테이너 종료 시 적용할 재시작 정책 지정. ([no |
--env, -e | 컨테이너의 환경변수 지정 (--env-file은 여러 환경 변수를 파일로 생성하여 지정하는 방법) |
-v, --volume=호스트경로:컨테이너경로 | 호스트 경로와 컨테이너 경로의 공유 볼륨 설정 (Bind mount라고 함) |
-h | 컨테이너의 호스트명 지정 (미 지정 시 컨테이너 ID가 호스트명으로 등록) |
-p [Host 포트]:[Container 포트], --publish | 호스트 포트와 컨테이너 포트 연결 |
-P, --publish-all=[true 나 false] | 컨테이너 내부의 노출된(EXPOSE) 포트를 호스트 임의의 포트에 게시 |
--workdir, -w | 컨테이너 내부의 작업 경로(디렉터리) |
위 옵션에서 실전 주요 명령어를 분석하면 아래와 같다.
-it : 해당 컨테이너에 뭔가 cmd할게 있으면 기재
-d : 컨테이너에 cmd할거 없이 백그라운드로 돌릴려면 이 옵션
-p : 호스트 PC의 포트랑 컨테이너 포트랑 연결하는 옵션
컨테이너 내부에서 구동중인 프로세스 목록 확인
docker top [컨테이너 이름 혹은 ID]

컨테이너의 세부정보를 JSON 형식으로 출력
docker inspect [컨테이너 이름 혹은 ID]

JSON 포멧으로 정보가 많이 나오기에 중요 정보를 취사해서 볼 필요성이 있다.
필자는 이 중 Port 정보만 따로 추출해서 사진에 붙였다.
docker attach랑 docker exec

지금 화면처럼 docker attach [컨테이너명]을 수행하면
아무 화면도 안나오는데 이것은 아까 node-run 컨테이너의 dockerfile에 기재한

기본 프로세스나 log확인같은 기본적인 상호작용만 수행할 때 사용하는 명령어이다.
exec는 해당 컨테이너에 접속하여 새로운 명령이나 더 상위의 상호작용을 수행하는 명령어로
통상 bash 쉘 스크립트나 기본 쉘 스크립트 접속해서 뭔가를 제어하는 경우가 주 이며,
아래의 명령어 세트로 사용하는게 일반적이다
# 새로운 상호작용 - 해당 컨테이너의 bash 쉘 스크립트 접속
docker exec -it [컨테이너명] bash
# 만약 bash 쉘 스크립트도 설치안된 경량 리눅스 계열일 시
docker exec -it [컨테이너명] sh

지금 접속하려는 node-run은 경량화가 많이 적용된 리눅스 계열이라서 bash 쉘 스크립트도 설치가 안되어 있어 기본 쉘 스크립트인 sh를 이용해야 한다.
docker commit
현재 활성화된 컨테이너에 무언가 변동사항이 발생하면 이를 image로 저장하는 기능을 제공하는 명령어이긴 한데...
필자는 dockerfile 이미지 빌드 파일을 바탕으로 작업을 수행하려 하기에 딱히 저장된 이미지가 필요한 편은 아니다..
오히려 용량관리만 안되서 이건 패스..
이것과 비슷한 것으로
docker export, docker import 라는 명령어가 있는데
이것은 특정 컨테이너를 아에 *.tar파일로 저장하는게 가능하다.
이거는 그냥 컨테이너를 백업하는 것이랑 같은 개념이다.