728x90
반응형
1. 컨테이너
- 이미지는 읽기 전용의 불변 값으로 만들어진다.
- 도커 엔진은 이미지를 이용해 컨테이너를 생성하며, 이때 읽고 쓰기가 가능한 레이어를 추가한다.
- 컨테이너 관련 명령어는 `dockerd` 데몬이 제공하는 docker CLI API를 통해 사용할 수 있다.
- 컨테이너는 프로세스이며, 도커 이미지를 기반으로 만들어진 snapshot이다.
- Snapshot은 도커 이미지 레이어(불변의 유니언 파일 시스템 - UFS)를 복제한 것이고, 그 위에 읽고 쓰기가 가능한 컨테이너 레이어를 결합되어 컨테이너가 생성된다. 이 컨테이너는 이것들만 가지고 실행된다.
- 애플리케이션은 프로세스를 통해 동작하며, 컨테이너는 격리된 공간에서 프로세스가 실행되는 기술이다.
- 리눅스 운영체제가 부팅되면 PID 1번인 init(systemd) 프로세스가 동작하고, 이 프로세스는 모든 프로세스의 부모 역할을 한다.
- 현재 호스트에서 실행 중인 프로세스 ID를 확인하려면 `$ echo $$` 명령을 사용한다.
👉 현재 호스트 컴퓨터인 리눅스가 1번 프로세스를 소유하고 있는데 docker로 수행한 컨테이너도 1번 프로세스를 소유할 수 있을까?
- `docker run` 수행 시 PID 네임스페이스 커널 기능을 이용해 호스트의 1번 프로세스를 공유하고, 도커의 컨테이너를 격리시킨다.
- 격리된 프로세스는 `chroot` 커널 기능을 통해 독립된 1번 PID를 갖게 된다.
- 격리된 컨테이너는 동작에 필요한 자원을 할당받아야 하는데, 이 기능은 cgroups를 통해 수행된다.
도커 컨테이너를 이해하기 위해서는 컨테이너에 제공되는 커널 기술을 알아야 한다.
→ chroot와 cgroups의 동작 원리를 이해
2. 컨테이너 실행
수동으로 컨테이너 제어
- 컨테이너 생성: `docker create` 명령
- 컨테이너 시작: `docker start` 명령
- 실행 중인 컨테이너 조회: `docker ps`
- 모든 컨테이너 조회: `docker ps -a`
#컨테이너 생성
$docker create -it --name container-test1 ubuntu:14.04
#실행 중인 컨테이너 조회: 컨테이너가 안 보임
$docker ps
#모든 컨테이너 조회
$docker ps -a
#컨테이너 동작
$docker start container-test1
#컨테이너에 접속 - attach
$docker attach container-test1
#attach로 컨테이너에 접속한 후 컨테이너에서 빠져 나 올 때는exit 명령을 사용하는데 이렇게 되면 컨테이너가 종료됨
#컨테이너 삭제
$docker rm container-test1
docker run: [docker image pull] + docker create + docker start + [command]
- 이미지가 없으면 다운로드
- 컨테이너 생성한 후 실행
- 이전 명령을 동일하게 수행
docker run -it --name container-test1 ubuntu:14.04 bash
- `-it` 옵션 과 `bash`를 붙이면 attach 와 동일한 기능을 수행
- `exit`를 입력하면 bash 쉘에서 빠져나오는데 이 때 컨테이너도 중지가 됩니다.
- 컨테이너를 만들 때 쉘에 접속을 하면 쉘을 빠져나올 때 컨테이너가 중지됩니다.
- 컨테이너 삭제: `docker rm container-test1`
옵션
- `-i`, `interactive`: 대화식 모드로 열기
- `-t`: 단말 디바이스 할당
- `-d`, `detach`: 백그라운드에서 컨테이너 실행 및 컨테이너 ID 등록
- `--name`: 컨테이너 이름 설정
- `--rm`: 종료 시 컨테이너 삭제
- `--restart`: 종료 시 재시작 정책 지정 (no | on-failure | on-failure:횟수 | always)
- `-e`, `env`: 환경 변수 설정
- `-v`, `volume`: 호스트와 컨테이너의 공유 볼륨 지정
- `-h`: 컨테이너의 호스트 이름 지정
- `-p`, `publish`: 호스트 포트와 컨테이너 포트 매핑
- `-P`: 컨테이너의 노출된 포트를 호스트의 임의 포트에 게시
- `--link`: 동일 호스트의 다른 컨테이너와 연결 설정. 연결이 되면 IP가 아닌 컨테이너 이름으로 통신이 가능
✅ MySQL 5.7을 이용한 SQL 테스트
- MySQL 5.7을 다운로드
docker pull mysql:5.7
- 이미지 확인
docker images | grep mysql
- 컨테이너를 실행하면서 쉘에 접속(운영체제는 쉘 이름만 입력하면 되지만 운영체제가 아닌 경우는 /bin/쉘이름)
docker run -it mysql:5.7 /bin/bash
- 설치 환경 확인
cat /etc/os-release
- 빠져 나오기: `exit`
- `docker run` 은 컨테이너를 생성하면서 시작한다.
- 중지된 컨테이너를 재시작하려면 `docker start {컨테이너ID | 컨테이너이름}` 사용
- 컨테이너에 명령 수행
docker exec [옵션] 컨테이너이름|컨테이너ID 명령어
- 현재 실행 중인 컨테이너의 bash 쉘에 접속
docker exec -it 컨테이너ID /bin/bash
- 컨테이너를 종료하지 않고 쉘에서 빠져나오기: `ctrl + p + q`
- 내부 IP 확인: `docker inspect 컨테이너이름 | grep IPAddress`
- bash에 접속: `docker exec -it 컨테이너이름 /bin/bash`
✅ Nginx 컨테이너 생성
- 이미지 다운로드: `nginx:1.18`
docker pull nginx:1.18
- 이미지 확인
docker images
- Nginx는 웹 서버 애플리케이션이므로 계속 동작해야 하며, 이를 위해 데몬으로 실행해야 한다. -d 옵션을 추가
- nginx는 웹 서버이므로 외부에서 접속을 할 수 있어야 한다 -> 포트포워딩을 설정해야 한다.
- 포트포워딩을 할 때는 p 옵션 다음에 호스트컴퓨터의 포트번호:컨테이너의포트번호를 설정해 줘야 한다.
- 컨테이너를 만들 때 컨테이너 이름을 설정하지 않으면 컨테이너 ID를 가지고 작업을 계속 수행해야 한다.
- 컨테이너 이름을 설정하는 것이 좋다.
nginx를 외부에서 8001 번 포트로 접속할 수 있도록 컨테이너를 생성
docker run --name webserver -d -p 8001:80 nginx:1.18
확인할 때는 docker ps 명령으로 컨테이너가 생성되었는지 확인 후,
`curl http://localhost:8001` 로 html 내용이 오는지 확인
🔵 리소스 사용량 확인
docker stats 컨테이너이름
docker stats webserver
docker run --name webserver -d -p 8001:80 nginx:1.18
- 종료하고자 하는 경우는 `ctrl + z`
- 브라우저나 다른 터미널에서 `localhost:8001` 에 접속해서 사용량을 확인
- 컨테이너 내부의 실행 중인 프로세스 확인: `docker top 컨테이너이름`
docker top webserver
🔵 컨테이너 내부의 로그 확인
docker logs -f(f는 실시간이고 t를 사용하면 마지막 로그 까지) 컨테이너이름
docker logs -f webserver
🔵 호스트 컴퓨터에서 컨테이너로 파일 복사
docker cp 호스트컴퓨터의파일경로 컨테이너이름:컨테이너내부파일경로
- nginx 의 첫 화면 파일을 확인
docker exec -it webserver /bin/bash
#cat /usr/share/nginx/html/index.html
- 컨테이너 외부에서 `index.html` 파일을 작성
$ vi index.html
<h1>File Copy</h1>
- 컨테이너 외부에서 컨테이너 내부로 파일을 복사
docker cp index.html webserver:/usr/share/nginx/html/index.html
- 웹 서버에 접속해보면 메인 화면이 변경된 것을 확인할 수 있다.
- 설정 파일을 컨테이너의 쉘에서 직접 수정할 수 있는 경우도 있지만 그렇지 못하는 경우가 많기 때문에, 외부에 설정한 후 `docker cp` 명령을 이용해서 복사해서 사용한다.
- 컨테이너 일시 중지: `docker pause 컨테이너이름`
- pause 된 컨테이너 다시 시작: `docker unpause 컨테이너이름`
- 컨테이너 다시 시작: `docker restart 컨테이너이름`
3. 파이썬 파일을 도커 컨테이너로 실행하기
- 파이썬의 기본 이미지는 python이다.
- 현재 작업 디렉터리에 파이썬 파일을 하나 작성한다. 리눅스에서 작업이 불편하면 윈도우에서 작성 후 git 명령 등을 사용해 복사할 수 있다.
- 파이썬 파일 py_lotto.py를 작성한다.
from random import shuffle
from time import sleep
gamenum = input('How many times? ')
for i in range(int(gamenum)):
balls = [x + 1 for x in range(45)]
ret = []
for j in range(6):
shuffle(balls)
number = balls.pop()
ret.append(number)
ret.sort()
print('lotto number[%d]:' % (i + 1), end=' ')
print(ret)
sleep(1)
작성한 파일을 실행하여 에러가 없는지 확인한다.
python3 py_lotto.py
파이썬 컨테이너를 실행한다.
docker run --name=python_test -dit -p 8900:8900 python
소스 파일을 컨테이너로 복사한다.
docker cp py_lotto.py python_test:/
도커 외부에서 파일을 실행한다.
docker exec -it python_test python /py_lotto.py
4. Node.js 애플리케이션을 도커 컨테이너로 실행하기
- Node.js의 기본 이미지는 `node`이다.
- Node.js로 웹 서버를 만들 때 포트를 직접 지정해야 한다.
- 웹 서버 코드를 `nodejs_test.js` 파일로 작성한다.
let http = require('http');
let content = function(req, res) {
res.writeHead(200);
res.end('Go for it Korea~!!!');
};
let web = http.createServer(content);
web.listen(8002);
8002번 포트를 외부에서 접근할 수 있도록 Node.js 컨테이너를 생성한다.
docker run -dit --name=nodejs_test -p 8002:8002 node
소스 코드를 컨테이너에 복사한다.
docker cp nodejs_test.js nodejs_test:/nodejs_test.js
실행 명령어를 수행한다.
docker exec -it nodejs_test node /nodejs_test.js
5. 컨테이너를 이미지로 만들기
명령 형식
docker commit [컨테이너 이름] [이미지 이름]
- `-a` 옵션을 이용해서 작성자를 추가해주기도 한다.
- 도커 허브에 있는 이미지를 다운로드하고 소스 코드를 추가하여 만든 이미지를 골든이미지라고 한다.
- Nginx의 welcome 파일을 변경한 이미지를 생성하여 테스트한다.
1. Welcome 파일 생성 (`index.html`):
<h1>Welcome My Web Site!!!</h1>
2. Nginx의 최신 버전으로 컨테이너 실행 (웹 서버 용도, 기본 포트 번호는 80)
docker run --name=website -dit -p 8008:80 nginx
3. 로컬 파일을 컨테이너로 복사:
docker cp index.html website:/usr/share/nginx/html/index.html
4. 변경 사항 확인:
curl http://localhost:8008
5. 컨테이너를 이미지로 생성:
docker commit -a adam website website:1.0
6. 이미지를 업로드 하기 위해 태그 작업 수행:
docker tag website:1.0 ggnagpae1/website:1.0
7. 이미지 업로드
docker push ggnagpae1/website:1.0
728x90
반응형