도커 다시 정리해보기

 

도커를 쓰는 기업이 많다. 거의 기본적으로 다 쓰고있다고 생각하면 된다.

크롬 같은 것을 실행하려고 하면 구글에 바로 검색해서 실행할 수 있는것이 아님.

 

installer 받고 실행해야되는데 이 경우 컴퓨터마다 설정이 다를 수 있고 에러가 날 수 있다.

 

이러한 문제를 해결해주는 것이 도커라고 생각하면된다.

 

도커에서 그럼 제일 많이 사용되는 용어 컨테이너,이미지 등등 명확하게 알고 넘어가야 됨.

 

컨테이너는 우리가 생각하는 그 컨테이너와 같고 그 컨테이너 안에는 우리가 사용하는 응용 프로그램이라고 생각하면된다.

sql,tomcat 등등 이러한 것이 컨테이너안에 있다고 생각하면된다.

 

컨테이너 이미지는 런타임,시스템 라이브러리 같은 설정 응용 프로그램 등 독립적인 실행 가능한 소프트웨어 패키지이다.

 

도커를 다운받고 설치해보자.

 

도커 공식 홈페이지에 들어가 자신 컴퓨터 운영체제에 맞는 installer를 설치한 뒤 로그인한다.

cmd를 이용하여 docker version을 썻을경우 해당과 같이 나오면 올바르게 설치된 것임.


도커 클라이언트에서 명령어를 입력하면 도커 서버에서 실행됨

 

docker run ~~~ 명령어 이용하여 도커 실행

Unable to find image나오면서 찾을 수 없다고 나온다.

hello-world라는 프로그램은 Hello from Docker! 같이 알려주는 이미지임 이걸 가져와서 pulling 해서 보여주는 것

 

내가 입력한 docker run ~ 명령어 입력하고 도커 서버로 이동함

hello-world라는 이미지 있는지 먼저 확인을 하고 없어서 도커 허브라는 곳에서 많은 이미지들 중에 해당 이미지를 가져온 것

 

가져온다는 문구 Pulling ~ 해서 해당 프로그램 실행된 것


도커 vs 가상화 기술 차이

 

만약 한대의 서버 100GB인데 하나의 용도로만 사용했는데 비효율적이였음

하이퍼 바이저 기반의 가상화가 출현하면서 vm이라는 가상 환경 서버를 이용하여  독립적인 가상 환경의 서버 이용이 가능하게 됨

 

하이퍼 바이저는 네이티브 하이퍼 바이저, 호스트형 하이퍼 바이저로 나뉨

네이티브 하이퍼바이저는 하드웨어 바로 위에서 하이퍼 바이저를 실행하고

호스트형 하이퍼바이저는 하드웨어 -> OS -> 하이퍼 바이저여서 OS위에서 하이퍼 바이저를 실행함

이렇게 되면 하이퍼바이저 위에 게스트 OS를 이용하여 윈도우를 설치하거나 리눅스 설치 가능

 

도커 컨테이너와 기존 가상화 기술은 기본 하드웨어에서 격리된 환경 내에 애플리케이션 배치하는 것

도커는 아까 호스트위에 OS를 배포하면 되는데

VM은 비슷하지만 VM을 띄우고 자원 할당, 게스트 OS 부팅해서 어플리케이션 실행해야돼서 훨씬 복잡하고 무거움.

 

카톡 컨테이너 , MYSQL 컨테이너 , 크롬 컨테이너 프로세스들이 실행되고 있고 

커널은 공유됨. (커널 : 소프트웨어,하드웨어 중재자)

하드디스크에도 카톡 컨테이너 , MYSQL 처럼 격리되어 있음.


아까말한 이미지들이 모여서 컨테이너가 되는데 어떻게 되는건지?

 

프로그램 실행한 필요한 설정들이 도커 이미지인데,

컨테이너안에서 프로그램을 실행하는건데 실행하는 명령어 필요함

run chrome 같은 명령어를 이미지에서 가지고 있고(예시임) 

chrome 파일도 가지고 있어야 함, 이렇게 모든 것을 가지고 있어야 함.

 

docker run chrome 이런식으로 실행하면 chrome 스냅샷을 하드 디스크에 넣어줌

 

명령어를 컨테이너에 넣어줘서 컨테이너가 실행할때 run chrome이라고 치면

컨테이너가 실행되고 커널을 통해서 하드디스크에 있는 크롬 파일 실행 , 네트워크 , ram , cpu 등등 이용 


크롬 , mysql 실행하기 위해 컨테이너 커널 하드 디스크에 파일 시스템이 있는데

이렇게 나누기 위해서 사용하는 것이 Cgroup과 네임 스페이스라고 했음

근데 이 Cgroup하고 네임 스페이스는 리눅스 환경에서 사용되는 것임..

근데 어떻게 windows에서 사용 가능한지?

docker version을 보면 server는 리눅스로 되어있음

 

도커는 리눅스 환경에서 돌아가고 있어서 나뉘어 질 수 있다고 보면 됨


도커 명령어 사용해보기

docker                          run              chrome

도커 클라이언트를 언급  실행한다 ~  크롬 이미지를 ~

 

도커 서버로 가짐.

도커 서버에서 컨테이너를 위한 이미지가 캐쉬에 있는지 확인한다.

없으면 도커 허브에서 받아옴.(Pulling)

 

docker run alpine ls

가져온다음 ls 파일 리스트 표출 커맨드를 보여줌

파일 스냅샷(필요한 설정파일들)이 하드디스크에 들어오고

ls명령어를 실행해서 목록이 보이는데 hello-world 했을때는 ls 안됐음.

alpine 이미지는 ls를 실행할 수 있는 파일이 있어서 가능한거고 hello-world는 없어서 그런것임.


현재 실행중인 컨테이너 나열 명령어 docker ps 바로 실행해봄

없어서 안나옴. ps(process status) 프로세스 상태

cmd 두개 켜서 하나는 실행 시키고 ps로 상태 찍어보면 나온다.

4번째 구문이 저장된 구문을 alpine이라는 컨테이너 이미지에 저장된 명령어를 통해 실행무시하고 해당 명령어를 실행시킴

 

docker ps를 이용하여 어떤 이미지가 실행되고 있는지 확인이 가능하다.

 

docker ps를 이용하면 몇가지 정보가 나오는데

CONTAINER ID : 컨테이너 고유한 해쉬값(일부만 나오는 것)

IMAGE : 컨테이너 생성시 사용 도커 이미지

COMMAND : 컨테이너 시작시 실행될 명령어

CREATED : 컨테이너 생성 시간

STATUS : 컨테이너의 상태

PORTS : 컨테이너가 개방한 포트와 호스트에 연결한 포트

NAMES : 컨테이너 고유 이름을 줄 수 있음(안하면 엔진이 알아서)

docker ps --format 'table{{.Status}}\table{{.Image}}'

원하는 항목만 볼 수 있음 Status보고 싶으면

 

 

>docker ps --format "table {{.Names}}\t{{.Image}}"

 

모든 컨테이너 보려면? 실행되지 않은 것도

docker ps -a

 


도커 컨테이너의 생명주기

크게는

생성(create)->시작(start)->실행(running)->중지(stopped)->삭제(deleted)

생성한 것 

신기하게도 아이디 앞에 몇글자만 복사해서 start 시키면 알아듣는다

-a옵션은 attach 붙이다 옵션임!

결과값 잘나온다.

docker run alpine ping localhost

알파인이용해서 핑 보내는 것 stop해보기

stop을 한 뒤에 느리게 종료되는 것 확인 

 

다음은 kill 시험

바로 종료가 되는 것 확인

 

삭제하는 방법은 중지된 후 

docker rm 아이디 또는 이름

원하는 컨테이너 삭제

모든 컨테이너 삭제 power shell 에서 명령어(cmd는 좀 복잡)

 

★ 도커 안쓰고 있는 컨테이너,이미지,네트워크 모두 삭제 ★

docker system prune

도커를 많이쓰면 용량이 커서 쓰지않을때도 용량을 많이 잡고 있어서 사용하면 유용하다.(실행중인 컨테이너에는 영향 X)

실행중인 컨테이너에 명령어 전달

실행중인 컨테이너에 명령어 전달하여 확인할 수 있음

run은 새로 실행 exec이미 실행된 프로세스 컨테이너에 명령어 전달 후 이용


도커에서 redis 실행

레디스 클라이언트가 레디스 서버가 있는 컨테이너 밖에서 실행을 하려 하니 레디스 명령어 불가능

레디스 클라이언트도 컨테이너 안에서 실행 시켜야 함

 

-it 명령어를 실행한 후 계속 명령어 적을 수 있음 

레디스 클라이언트에서 redis-cli명령어를 써야하므로 exec로 실행중인 컨테이너에 명령어 보내야 함 -it 옵션을 적지 않으면

바로 들어갔다 그냥 나와버리는게 되므로 명령어를 전달하려면 -it 옵션을 넣어야함.


먹히지 않은 명령어 같은 경우 쉘환경이 안맞아서 powershell을 켜서 진행했는데

docker exec -it 컨테이너 명령어(powershell)

이런식으로 쉘 환경으로 접근이 가능하다고 함 바로 해본다!

알파인 실행하고 해보는데 잘 안됨.. cmd에서는 $() 또는 백틱(`)을 지원하지 않아서 그런 것 같음

 

다른 명령어로 학습해본다.

ls는 잘 접근

ctrl + C로 잘 안나와짐 ctrl + D로해야 나와진다.

docker run -it mcr.microsoft.com/powershell pwsh

powershell 쓰려면 powershell 컨테이너 실행시켜서 쓸 수 있다는데 해당 도커를 쓰려고 하니 안됨

 

왜냐하면 파워쉘을 실행시키는데 이 파워쉘안에는 도커의 cli나 도커의 서버(데몬)이 없기 때문


도커 이미지 만들기

 

도커파일작성 > 도커 클라이언트 > 도커 서버 > 도커 이미지 생성

도커 파일에서는 컨테이너가 어떻게 행동해야 하는지 설정해둠

 

도커 파일 만드는 순서

1. 베이스 이미지를 명시(레이어들로 구성되어 있는 이미지에서 가장 근본이 되는 레이어 ex) OS)

2. 추가적 필요 파일 다운 몇가지 명령어

3. 컨테이너 시작시 실행 될 명령어

 

바탕화면에 폴더 생성

폴더 vcs로 오픈 후 Dockerfile 생성

FROM RUN CMD 이용해서 도커 서버에게 무엇을 하라고 알려주는 것

 

FROM 이미지 받으라고 하는 것

RUN 도커이미지가 생성되기 전에 수행할 쉘 명령어

CMD 컨테이너가 시작되었을 때 실행할 실행 파일 또는 셸 스크립트

알파인써서 hello 출력하는 도커 파일 생성

생성했으면 build 해야 함

빌드 된 것

 

이미지로 컨테이너를 만들어야 함

<none> 상태로 아직 이름을 가지지 않은 상태

하지만 실행시킬때 저 ID 값으로 하면 입력하기 어려우니 저걸 바꿔줘야함

build할때 옵션을 넣어주면 됨

 

docker build -t kaki5507(도커아이디)/FlyOn(저장소/프로젝트이름):버전

이런식의 규칙이 있음

소문자로만 작성해야함 안그러면 오류

docker run -it kaki5507/flyon


도커 실습해보기

node package.json 만들어줌 명령어 npm init해서 생성

라이브러리 하나 추가할거임

{
  "name": "nodejs-docker",
  "version": "1.0.0",
  "main": "server.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [
    "kaki5507"
  ],
  "author": "",
  "license": "ISC",
  "description": "",
  "dependencies": { 
    "express" : "^4.21.1" // express 추가한 것 최신버전
  }
}

 

node js 앱 만들꺼임

server.js 생성해서 해당 코드 삽입

const express = require('express'); // express 가져와줌

const PORT = 8080;

// express 앱 생성
const app = express();
app.get('/', (req,res) => {
    res.send("Hello World");
});

app.listen(PORT); // 설정 된 포트에서 앱실행해야됨

이제 도커파일 생성할 것

FROM RUN CMD ! 위에 예제했던대로 먼저 해야 될 것 작성

# 베이스 이미지 명시
FROM node:10

RUN npm install

CMD ["node", "server.js"]

npm install을 하려면 npm이 가지고 있는 이미지가 필요한데 그게 node 이미지임

node 이미지는 npm도 있고 다른것도 많음

 

npm Node.js 모듈 웹에서 받아서 설치하고 관리해주는 프로그램

npm install은 package,json에 적혀있는 종속성들을 웹에서 자동으로 다운 받아 설치

 

build해서 성공 하지만 실행 시 되지 않았음

 

C:\Users\ckdbi\Desktop\nodejs-docker>docker run ec45af266bd5c5
internal/modules/cjs/loader.js:638
    throw err;
    ^

Error: Cannot find module '/server.js'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:636:15)
    at Function.Module._load (internal/modules/cjs/loader.js:562:25)    at Function.Module.runMain (internal/modules/cjs/loader.js:831:12)
    at startup (internal/bootstrap/node.js:283:19)
    at bootstrapNodeJSCore (internal/bootstrap/node.js:623:3)

server.js를 찾을 수 없다라고 나온다.

 

Node 베이스 이미지로 node:10을 입력했고 이걸로 임시 컨테이너를 만들려고 하고 , 환경을 하드 디스크에 넣어주는데

npm install을 하려고 할때 package.json이 없다고 나옴 컨테이너안에 있는것이 아니고 package.json이 바깥에 있어서 하드 디스크가 들어있지 않음. package.json을 컨테이너 안으로 넣어줘야 사용이 가능

COPY해서 사용해야 됨.

 

FROM RUN CMD 이렇게 있었는데 COPY 부분을 추가해줘야함

 

# 베이스 이미지 명시
FROM node:10

COPY package.json ./

RUN npm install

CMD ["node", "server.js"]

 

이렇게 설정해두고 다시 빌드해본다.

 

docker build -t kaki5507/nodejs ./

 

$ docker run kaki5507/nodejs
internal/modules/cjs/loader.js:638
    throw err;
    ^

Error: Cannot find module '/server.js'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:636:15)
    at Function.Module._load (internal/modules/cjs/loader.js:562:25)    at Function.Module.runMain (internal/modules/cjs/loader.js:831:12)
    at startup (internal/bootstrap/node.js:283:19)
    at bootstrapNodeJSCore (internal/bootstrap/node.js:623:3)

 

또 못찾음 .. server.js도 밖에서 있어서 그런 것 안에다 넣어줘야한다.

 

dockerfile 다시 수정

# 베이스 이미지 명시
FROM node:10

COPY ./ ./

RUN npm install

CMD ["node", "server.js"]

실행된 화면을 볼 수 있음

console.log("서버 돌아가고 있음")
app.listen(PORT); // 설정 된 포트에서 앱실해애됨

표시가 안나서 console.log 하나 찍어준다음 다시 빌드해서 도커 실행

그리고 localhost8080해서 들어갔는데 뭐 나오는 건 없음 해당 포트 구문 8080 hello world 찍어주는 화면이 나와야하는데

 

왜 접근을 못하는지 ? - 현재 포트가 매핑되어 있지 않기 때문 

 

우리가 8080을 준다고 해도 컨테이너안에 있는 네트워크 8080에 들어갈 수 있는것이 아님

매핑을 시켜줘야지 들어갈 수 있다.

-p : 포트 매핑 명령어를 이용하여 들어갈 수 있다.

 

docker run -p 5000 : 8080 이미지 이름

 

5000번으로 매핑 후 브라우저에서 접속하는 모습


도커 워크 디렉토리

FROM  WORKDIR COPY RUN CMD

무슨 옵션인지 ? 왜 필요할까 ? 

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

COPY 한것들이 이미지로 루트로 들어오게 됨

이러면 원래 루트 디렉토리에 있는 파일이 만약 이름이 같을 경우 COPY한 파일이 덮어써질 수 있음

+ 너무 복잡함 

 

이러한 문제를 해결하기 위해서 WORKDIR를 설정해서 깔끔하게 작성한다.

# 베이스 이미지 명시
FROM node:10

WORKDIR /usr/src/app

COPY ./ ./

RUN npm install

CMD ["node", "server.js"]

다시 이미지 빌드

워크디렉토리로 바로 연결돼서 정리된게 보임
찾아서 들어가보면 파일들 잘 정리되어 있음


도커를 계속해서 빌드해야되는건가 ...

docker run -d -p 5000:8080 kaki5507/nodejs

-d 옵션 바로 빠져나오게 하는 것 포트 매핑

const express = require('express'); // express 가져와줌

const PORT = 8080;

// express 앱 생성
const app = express();
app.get('/', (req,res) => {
    res.send("Hello World2222222");
});
console.log("서버 돌아가고 있음")
app.listen(PORT); // 설정 된 포트에서 앱실해애됨

이렇게 Hello World222222가 출력되게 하고 싶음( 또 빌드 해야함 비효율적 ) 

# 베이스 이미지 명시
FROM node:10

WORKDIR /usr/src/app

# package.json COPY 먼저
COPY package.json ./

RUN npm install

# RUN 밑으로 내림
COPY ./ ./ 


CMD ["node", "server.js"]

패키지 부분을 먼저 카피를 해주고 package.json부분을 카피함

지금까지는 npm start하면서 package.json을 계속 다시 받은거였음

RUN 위에 COPY로 먼저 안바뀔 설정들을 받아두는게 좋음

나머지 변경되는 소스들을 아래로 내려서 캐시를 이용해서 받아 빠른 수정사항을 적용시킬 수 있었음.

CACHED 사용 부분


Docker Volumes이란?

COPY는 내 로컬에있는 파일을 도커 컨테이너로 옮기는 것인데

Volume은 도커 컨테이너가 내 로컬을  참조하는 것

 

cmd 에서 명령어

C:\Users\ckdbi\Desktop\nodejs-docker>docker run -d -p 5000:8080 -v /usr/src/app/node_modules -v %cd%:/usr/src/app kaki5507/nodejs

git bash에서는 $(pwd) 이용

docker run -d -p 5000:8080 -v /usr/src/app/node_modules -v $(pwd):/usr/src/app kaki5507/nodejs

 

docker run -d -p 5000:8080 -v /usr/src/app/node_modules -v %cd%:/usr/src/app kaki5507/nodejs

-v /usr/src/app/node_modules : 내 usr/src/app에는 node_modules 없어서 제외

 (호스트 경로 지정안되어 있음 , 이 경우 Docker는 해당 볼륨을 데이터 볼륨으로 처리 , 호스트의 파일 시스템과는 독립적으로 데이터 유지)

-v %cd%:/usr/src/app : 나머지는 내 디렉토리 %cd%에서

(현재 디렉토리 가르킴 %cd% 동기화되어 상호 공유)

근데 윈도우에서 Volume이용하면 바로 바뀌지 않는다 무슨 문제인지 cmd로 빌드했을 경우 잘됨 

CMD 결과

 

  • 경로 호환성 문제: Windows와 Git Bash 간 경로 처리 방식 차이로 Docker가 파일을 제대로 마운트하지 못함.
  • 권한 문제: Git Bash에서 Docker가 파일 시스템 권한을 올바르게 인식하지 못해 동기화 실패.

 

winpty docker run -d -p 5000:8080 -v $(pwd):/usr/src/app kaki5507/nodejs

1. 

 

권한 문제 라고 생각했을 경우 해결 방법으로 winpty를 사용해서 windows 응용 프로그램과의 호환성 문제를 해결할 수 있다고 한다.

바로 적용해본다.

결과 : 빌드전으로 돌아감 Hello World가 나옴

 

2.

docker run -d -p 5000:8080 -v "$(cygpath -w "$(pwd)")":/usr/src/app kaki5507/nodejs

$(cygpath -w "$(pwd)") : 현재 디렉토리 Windows 경로로 변환

이 문제는 아닌 것 같다 해결 안됨. 결과 동일.

 

3.

Nodemon 사용하기 Node.js 애플리케이션이 자동으로 파일 변경을 감지하도록 설정

FROM node:14
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install -g nodemon
RUN npm install
COPY . .
CMD ["nodemon", "server.js"]

해본 결과 안됨.. 재빌드 했는데 일단 CMD를 이용..

+ Recent posts