728x90

쿠버네티스 입문반 Introduction to Docker

첫 수업으로 Introduction to Docker 강의를 들었습니다. 구글 클라우드 환경에서 터미널에 접속해 docker를 실행하고 실습하는 시간이 되었습니다. docker기본을 배우고 듣는 수업이라 어려운 수업은 아니였습니다. 강의가 영어로 되어있어 살짝 힘든 것 말고는 좋은 학습이 될 것 같습니다. 혹시 몰라 구글에서 사용하는 아이디는 모자이크 처리하였습니다.

 

구글 클라우드 쉘에 접속한 모습입니다. 여기서 쿠버네티스 실습을 진행합니다.

 

docker run hello-world

위의 사진을 잘 보시면 Unable to find image를 보실 수 있습니다. docker 데몬은 hello-world 이미지를 검색했지만 로컬에서 이미지를 찾지 못해서 Docker Hub라는 공개 레지스트리에서 이미지를 가져와서 해당 이미지에서 컨테이너를 생성하고 컨테이너를 실행했습니다.

 

docker images

docker images 명령어입니다. 이 스크린 샷은 못 찍었습니다. 이미지 목록을 확인하는 명령어입니다.

 

docker run hello-world

정상적으로 실행되었습니다. Hello from Docker !

 

docker ps

docker ps 명령어입니다. 실행 중인 컨테이너가 없습니다. 이전에 실행한 hello-world 컨테이너가 이미 종료되었습니다. 

 

docker ps -a

종료된 컨테이너를 포함하여 모든 컨테이너를 보려면 docker ps에서 - a 옵션만 추가시켜주면 됩니다.

 

mkdir test
cd test

test 디렉터리를 만들고 test 디렉터리에 들어갑니다. 

 

cat > Dockerfile <<EOF
# 공식 Node 런타임을 부모 이미지로 사용 
FROM node:lts
# 컨테이너의 작업 디렉터리를 /app으로 설정 
WORKDIR /app
# 현재 디렉터리 내용을 /app으로 설정
ADD . /app
# 컨테이너의 포트 80을 외부에서 사용할 수 있도록 설정.
EXPOSE 80
# 컨테이너가 실행될 때 node를 사용하여 app.js를 실행합니다. 
CMD ["node", "app.js"]
EOF

dockerfile을 만드는 방법에 대한 설명입니다. 간단하게 실습하는 것이라 명령어에 잘 모르실 경우 제 블로그 참고 바랍니다.

https://lusida-coding.tistory.com/35?category=1031465 

 

따배도) Docker 명령어, dockerfile 만들기 및 repo배포

따라 하며 배우는 도커 유튜브 영상을 보고 학습한 내용을 블로그에 정리하려고 합니다. 1. 도커 기본 명령어 docker docker를 설치하셔서 docker를 치면 docker에 관련된 명령어들이 나온다. docker search

lusida-coding.tistory.com

 

cat > app.js <<EOF
const http = require('http');
const hostname = '0.0.0.0';
const port = 80;
const server = http.createServer((req, res) => {
    res.statusCode = 200;
    res.setHeader('Content-Type', 'text/plain');
    res.end('Hello World\n');
});
server.listen(port, hostname, () => {
    console.log('Server running at http://%s:%s/', hostname, port);
});
process.on('SIGINT', function() {
    console.log('Caught interrupt signal and will exit');
    process.exit();
});
EOF

노드 애플리케이션 파일을 만듭니다. 포트 80에서 수신 대기하고 Hello World를 출력하는 간단한 HTTP 서버입니다.

 

docker build -t node-app:0.1 .

 

이미지를 빌드합니다. "."은 현재 디렉터리를 의미하므로 Dockerfile이 있는 디렉토리 내에서 이 명령어를 실행해야 합니다.

 

node은 기본 이미지이며 node-app빌드한 이미지입니다. node먼저 제거하지 않고는 node-app을 제거할 수 없습니다. 이미지의 크기는 VM에 비해 상대적으로 작습니다.

 

docker run -p 4000:80 --name my-app node-app:0.1

방금 빌드한 이미지를 기반으로 컨테이너를 실행합니다. 현재 터미널에서 실행되는 것을 확인하실 수 있습니다.

 

curl http://localhost:4000

--name은 원하는 경우 컨테이너의 이름을 지정할 수 있습니다.호스트 의 -p포트 4000을 컨테이너의 포트 80에 매핑하도록 명령어를 작성했다. 이제 http://localhost:4000. 포트 매핑이 없으면 localhost의 컨테이너에 연결할 수 없습니다. 다른 터미널을 열고 서버를 테스트합니다. Hello World가 정상적으로 출력되는 것을 확인하실 수 있습니다.

 

docker stop my-app && docker rm my-app

컨테이너를 중지하고 컨테이너를 지우는 명령어입니다.

 

docker run -p 4000:80 --name my-app -d node-app:0.1

컨테이너를 백그라운드에서 실행하려면(터미널 세션에 연결되지 않음) -d옵션을 지정해야 합니다.

 

docker logs my-app

컨테이너의 로그를 확인하는 명령어입니다.

docker logs -f [container_id]

 컨테이너가 실행될 때 로그의 출력을 실시간으로 확인하려면 -f옵션을 사용하면 됩니다.

 

docker build -t node-app:0.2 .

app.js파일에서 Hello World를 Hello Cloud로 수정 후 node-app:0.2로 빌드를 진행하였습니다.

2단계에서 기존 캐시 계층을 사용하고 있음을 알 수 있습니다. 3단계부터 에서 변경했기 때문에 레이어가 수정됩니다.

 

docker run -p 8080:80 --name my-app-2 -d node-app:0.2
curl http://localhost:8080
curl http://localhost:4000

새 이미지 버전으로 다른 컨테이너를 실행합니다. 호스트 포트 4000은 이미 사용 중이기 때문에 사용할 수 없습니다. 컨테이너를 실행 후 curl로 8080과 4000에 접속 테스트를 진행하였습니다. 8080에는 모자이크로 잘리긴 했으나 Hello to Cloud가 출력되었고 4000에는 수정하기 전인 Hello World가 출력되었습니다.

 

docker exec -it [container_id] bash

실행 중인 컨테이너 내에서 Bash 세션을 시작할 때는 명령어 마지막에 bash라고 지정해주면 됩니다. docker exec -it를 사용하면 pseudo-tty를 할당하고 표준 입력을 열린 상태로 유지하여 컨테이너와 상호 작용할 수 있습니다. bash는 Dockerfile에 WORKDIR지정된 디렉터리(/app)에서 실행되었습니다.

 

docker inspect [container_id]

Docker inspect를 사용하여 Docker에서 컨테이너의 메타데이터를 확인할 수 있습니다.

docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' [container_id]
--format은 반환된 JSON에서 특정 필드를 검사하는 데 사용 합니다.
위의 예시는 IPAddress을 확인하는 명령어입니다.
 

docker tag node-app:0.2 gcr.io/[project-id]/node-app:0.2

도커를 푸시를 해주려면 컨테이너에 태그가 붙어있어야 합니다. 제 개인 도커 레파지토리에 푸시를 하려면 제 도커 레파지토리 이름 태그를  붙여줘야 합니다.

docker push gcr.io/[project-id]/node-app:0.2

도커를 gcr에 푸시하는 명령어입니다. 

 

728x90
728x90

컨테이너 간 통신(네트워크) 명령어

1. 컨테이너 통신 방식

도커 데몬을 실행하게 되면 docker0라고 하는 도커 네트워크 인터페이스가 생긴다. 도커 네트워크 인터페이스는 virtual ethernet bridge이고 브릿지 네트워크를 지원하는 가상 네트워크이다. 브릿지 네트워크는 도커 컨테이너가 가지고 있는 IP와 Host 이더넷 또는 물리 장비가 가지고 있는 네트워크를 연결해주는 역할을 한다. 브릿지 네트워크를 지원하기 위해서 docker0는 내부적으로 NAT서비스와 포트 포워딩 기능을 제공한다. 직접 도커가 지원하는 것은 아니고 IPtables로 해준다. virtual ethernet bridge : 172.17.0.0/16 값을 가지는 브릿지 네트워크가 docker0이고 브릿지 네트워크 안에서 docker0는 172.17.0.1 IP를 가지고 게이트웨이 역할을 한다. 컨테이너의 게이트웨이 역할과 L2통신을 지원해준다. 모든 컨테이너는 외부 통신을 docker0를 통해 진행한다. 컨테이너가 실행되면 172.17.x.x로 순차적으로 가상 IP를 할당한다.

 

-NAT : Network Address Translation의 약자로 패킷이 라우팅 장치를 통해 전송되는 동안 패킷의 IP주소 정보를 수정하여 IP 주소를 다른 주소로 매핑하는 방법이다.

-IPtables : iptables 시스템 관리자 리눅스 커널 방화벽(다른 넷필터 모듈로 구현됨)이 제공하는 테이블들과 그것을 저장하는 체인, 규칙들을 구성할 수 있게 해주는 사용자 공간 응용 프로그램이다.

 

2. 컨테이너 포트를 외부로 노출

클라이언트는 eth0라는 인터페이스를 통해서만 들어올 수 있다. eth0에서 컨테이너까지 연결될 수 있도록 포트 포워딩이 진행되야한다.

-p 80:80 -p 호스트 포트:컨테이너 포트

-p 8080로 하면 실제로는 -p randomport:8080이 된다.

-P는 컨테이너 내부에서 도커 파일의 EXPOSE로 정의되어있는 포트에 맞춰서 렌덤 포트가 자동으로 맞춰진다.

 

3. user-defined bridge network 생성 방법

docker network create --driver bridge --subnet xxx.xxx.xxx.x/24 --gateway xxx.xxx.xxx.xxx mynet

subnet을 정해주지 않으면 docker0가 172.17.0.1을 사용하고 있으므로 172.18.0.1로 된다.

gateway를 생략하면 xxx.xxx.xxx.1번으로 된다.

 

docker network ls

위의 명령어는 docker의 네트워크 확인하는 명령어이다.

 

docker run -d —-name appjs —-net mynet —-ip 192.168.100.100 -p 8080:8080 smliux/appjs

위의 명령어는 docker에서 유저가 정의한 네트워크를 실행할 때의 명령어이다.

-ip 생략하면 순차적으로 알아서 생긴다. ex) 192.168.100.001 , 192.168.100.002 등등

 

4. 컨테이너끼리의 통신

프론트 컨테이너와 백엔드 컨테이너가 통신을 할 때를 예를 들면 wordpress가 있는데 wordpress는 웹페이지를 쉽게 제작할 수 있게 도와주는 Tool이다. wordpress 안에는 아파치 웹서버가 내장되어 있다. 또한 wordpress에서 만들어진 데이터는 MySQL에서 저장되게 구성되어있다.

 

mysql 실행

docker run -d —-name mysql -v /dbdata:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=pass -e MYSQL_PASSWORD=pass mysql

 

wordpress 실행

docker run -d —-name wordpress —-link mysql:mysql -e WORDPRESS_DB_PASSWORD=pass -p 80:80 wordpress

컨테이너와 컨테이너끼리의 통신은 --link를 통해서 연결된다. 컨테이너 이름:원하는 이름

 

728x90
728x90

따배도 강의를 보고 실습을 하다가 발생하는 오류를 작성했습니다.

1. no matching manifest 오류

MySQL을 실행시키려고 명령어를 작성하였는데 no matching manifest 오류가 발생하였습니다.

해결 방법은 간단했습니다. 실행시킬 때 플랫폼 주소도 함께 작성해주면 해결됩니다.

docker run --platform linux/amd64 -d --name db -v /data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=pass mysql:latest

성공적으로 실행이 되는가 했는데 이번에는 Mounts denied 오류가 발생하였습니다.

 

2. Mounts denied 오류

우선 docker desktop 화면에서 오른쪽 상단에 보시면 Settings에 톱니바퀴의 이미지가 있습니다. 클릭합니다.

 

Settings를 클릭하시면 위와 같은 화면이 나오실 텐데 위에 화면에서 Resources에서 FILE SHARING을 클릭해 줍니다.

그 화면에서 마운트를 진행할 폴더를 설정해줍니다. 설정하시고 오른쪽 하단에 Apply&Restart 버튼을 눌러줍니다.

 

다시 MySQL을 Run하시면 정상적으로 동작하는 것을 확인하실 수 있습니다.

728x90
728x90

도커 실행과 종료의 관련된 명령어

docker create --name webserver nginx

create 명령어는 기본 백그라운드에서 실행된다. nginx가 webserver라는 이름으로 컨테이너가 생성된다.

 

docker start webserver

컨테이너로 만든 webserver를 실행시켜주는 명령어이다.

 

docker run --name webserver -d nginx

docker pull, create, start를 한 번에 진행하는 명령어이다.

 

docker ps -a

docker ps 명령어와 docker ps -a 명령어의 차이는 docker ps는 실행 중인 컨테이너만 보인다.

docker ps -a 는 실행과 중단된 컨테이너 모두 보인다.

 

docker inspect webserver

컨테이너의 상세 내용을 볼 수 있다.

 

docker inspect --format '{{.NetworkSettings.IPAddress}}' web

컨테이너의 상세 NetworkSetting.IPAddress 의 설정만 볼 수 있는 --format 옵션이다.

 

1. docker logs web
2. docker logs -f web

1. web의 이름을 가진 컨테이너의 로그를 확인할 수 있다.

2. web의 이름을 가진 컨테이너의 실시간 로그를 확인할 수 있다.

 

docker exec -it webserver /bin/bash

-it 옵션을 사용해 컨테이너에 직접 접속해서 배쉬 쉘 사용할 수 있다.

728x90

+ Recent posts