[Docker] MySQL과 Nginx를 활용한 Docker 컨테이너 만들기

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
반응형