[0707]Docker

nikevapormax·2022년 7월 7일
0

TIL

목록 보기
65/116
post-thumbnail

Docker

Docker가 없다면?

서버란?

  • 우리가 작성한 코드를 실제로 서비스하는 컴퓨터

서버 운영 without Docker

  • 서버에서 작성한 코드를 실행하기 위해 아래의 과정들이 진행되어야 한다.
    • os 설치
    • 실행환경 세팅(python)
    • 어플리케이션 코드(또는 빌드) 다운로드
    • library 다운로드 등등
  • 서비스를 운영할 때 필요한 서버 운영작업은 아래와 같다.
    • 보안 결함
    • 필요 시 새로운 코드 또는 라이브러리 추가 가능
  • 우리가 많은 수의 요청을 처리하기 위해서는 많은 수의 서버를 필요로 하게 된다.
    • 운영의 편리성을 위해 스크립트를 작성해 사용하게 된다.
  • 하지만 서버를 운영하다 보면 운영체제 변경, 사용 언어의 버전 관리, 실행환경 세팅 언어 변경 등의 여러 요청들이 생기게 된다.
  • 만약 서비스의 규모가 작다면 일일이 변경해주는 것이 가능하겠지만, 서버가 몇백 몇천대가 있다면 일일이 변경해주는 것은 사실상 불가능할 수도 있다.
    • 각 서버마다 필요로 하는 요구사항이 다를 수 있다.
    • 서버의 코드가 작동하지 않을 수도 있다.
    • 간헐적으로 문제가 생기는 경우 이슈를 찾는데 시간이 많이 소요된다.

Docker를 사용한다면?

Docker란?

  • 원하는 프로그램을 쉽게 실행하기 위한 플랫폼

Docker의 발상

  • 서버 운영에서 인프라 관리어플리케이션 작성을 분리해보자!
  • 그래서 도커는 도커 이미지라는 것을 만들어 실행환경, 실행하는 코드, 필요한 라이브러리, 설정 파일을 한 곳에 정의해 주었다.
  • 따라서 서버에서는 각각의 설정을 일일이 하는 대신 그저 이미지를 실행하기만 하면 된다.
  • 아래의 3 가지를 고려해야 한다.
    • 이미지를 생성하는 법
    • 이미지를 공유하는 법
    • 이미지를 실행하는 법

Docker의 구성 요소

  • docker image & container
    • image : 어플리케이션을 실행하기 위한 필요한 모든 것이 생성되어 있는 파일
    • container : image를 사용하여 실행한 것
      • 프로세스의 독립성을 보장하기 위해서 네트워크나 저장소 분리
  • docker registry
    • docker image를 저장하는 공간
  • dockerd
    • docker API requests를 받아서 docker object(image, container등)를 관리
  • docker client
    • 사용자가 docker를 사용하기 위해서 사용하는 cli(Command-line interface)

Docker와 비슷한 이전 기술

  • 가상 머신(VM; Virtual machine) 기술이 있다.
    • 하이퍼바이저를 사용해서 여러개의 운영체제를 하나의 호스트에서 생성해 사용하는 방식
  • VM vs. Docker

Docker 설치

  • 아래의 링크를 눌러 설치 페이지로 이동할 수 있다.

    Docker Download

  • 다운을 마치고 도커를 키면 하단의 주황색 박스를 볼 수 있다. 이 박스가 초록색이 될 때까지 기다려야 한다.

  • 도커가 잘 세팅되었는지 확인해보자.
    • 아래의 명령어를 커맨드창에 입력하고, 아래와 같은 결과가 나오면 된다.
      $ docker
    • 빨간 박스가 위의 명령어이다.
    • 그리고 아래의 명령어를 쳐 아래 결과가 나오면 docker 사용준비 완료!
      $ docker ps

Docker 실습

간단한 애플리케이션 실행

  • 아래의 코드를 커맨트창에 입력해 애플리케이션을 실행해보자.
    • 처음에 Unable to find image 'docker/getting-started:latest' locally라는 메세지가 나와 당황했는데, 그냥 가만히 있으면 결과에서 보이는 것과 같이 뭔가를 pull해오면서 알아서 세팅해준다.
    • 당연히 이미지가 없는게 맞는데 unable을 보자마자 ptsd가 올 뻔했다.ㅋ
$ docker run -d -p 80:80 docker/getting-started

  • 이제 브라우저로 건너가서, 주소창에 딱 localhost만 입력하면 아래와 같은 튜토리얼 화면이 나오게 된다.
  • 방금 전 입력했던 코드의 원리를 한 번 알아보자.
  • 방금 전 ptsd가 올 뻔했던 메세지를 한 번 보자면
    • Unable to find image 'docker/getting-started:latest' locally
    • 즉, 내 로컬 pc의 doker image 목록docker/getting-started라는 이름의 이미지가 없다는 뜻이었다.
    • 그러므로 도커는 자동적으로 docker registry에서 해당 이미지를 찾았고, 찾은 이미지를 로컬로 다운로드 받게 된다.
    • 그리고 doker run이라는 명령어를 통해 container를 생성해 위의 브라우저 화면을 보여주게 되는 것이다.

Docker run 기본 문법

$ docker run [options] {image_name} [command]
  • docker run : docker image를 사용해서 container를 실행하는 명령어
  • 그렇다면 우리가 사용할 수 있는 options에는 무엇이 있을까?
    • 아래의 명령어를 커맨드창에 입력해보면 사용할 수 있는 것들이 나온다.
      $ docker run --help
    • 아래의 결과보다 더 많은 결과가 나오게 된다.
  • 아까 우리가 사용했던 명령어를 설명해보도록 하자.
$ docker run -d -p 80:80 docker/getting-started
  • -d : detach option이며, 실행한 docker container가 백그라운드에서 실행되도록 하여 컨테이너가 실행되는 프로세스를 커맨트창에 보여지지 않도록 해준다.
  • -p : publish라는 옵션이며, 기본적으로 docker/getting-started는 웹 서비스이다보니 80번 포트를 제공받아 사용되고 있는데, 우리는 localhost에서도 접속을 해야 하므로 80번 포트와 localhost를 연결해 주는 명령어이다.
    • 기본적으로는 네트워크가 연결되어 있지 않다.
  • 80:80
    • 앞의 80 : 호스트 포트
    • 뒤의 80 : container 내부에서 서빙하고 있는 포트

container 상태 확인하기

  • 현재 실행되고 있는 container 확인하기
    • 실행 코드
      		$ docker ps
    • 실행 결과
    • CONTAINER_ID : 도커가 실행될 때마다 받는 고유 ID 값
    • IMAGE : docker container를 띄울 때 사용된 이미지
    • COMMAND : container가 실행될 때 어떤 커맨드를 주었는지
      • 우리는 아까 command를 따로 입력하지 않았다.
      • 그러므로 위에 있는 코드는 이미지에 적용되어 있던 command이고, 이것이 자동적으로 실행된 것이다.
    • CREATED : 얼마 전에 생성되었는지
    • STATUS : 지금 상태가 어떤지
      • 현재는 23분동안 실행중이다.
    • PORTS : publish option에서 주었던 80포트와 80포트가 연결되는 부분
    • NAMES : container의 이름
      • 현재 이름을 적용해준 적은 없다. (랜덤 자동 생성)
      • 나중에 container를 편리하게 사용하기 위해 이름을 붙여줄 수 있다.

container 실행 멈추기

  • 도커를 멈출 수 있는 명령어는 2 가지가 있다.
  • kill
    • 명령어
      $ docker kill {container_id|conatinaer_name}
    • SIGKILL이라는 신호를 보냄
    • 바로 삭제를 해달라는 요청
  • stop
    • 명령어
      $ docker stop {container_id|conatinaer_name}
    • SIGTERM이라는 신호를 보냄
    • 종료를 해달라는 요청
  • 도커를 멈춰보도록 하겠다. 앞에서 실행한 것을 멈출 것이며 CONTAINER_ID를 같이 입력해주면 된다.
    $ docker stop f6a574ab40d8(CONTAINER_ID)
  • 이제 브라우저를 확인해도록 하겠다.

실행이 멈춘 docker container 상태 확인하기

  • 아래의 명령어를 실행한다.
    • docker ps의 경우, 현재 실행중인 container에 대한 정보를 보여주기 때문에 주의해야 한다.
$ docker ps -a

  • STATUS를 보면 언제 멈췄는지 볼 수 있다.

실행이 멈춘 docker container 다시 실행하기

  • 아래의 명령어를 실행한다.
$ docker restrat CONTAINER_ID
  • 오타 주의! ㅎㅎ
  • 브라우저로 가면 다시 튜토리얼 페이지가 실행되는 것을 볼 수 있다.

실행중인 docker container에서 명령어 실행하기

$ docker exec [options] {container_id|container_name} [command]
  • 먼저 지금 돌아가고 있는 container의 내부 구조를 한 번 보자.
$ docker exec CONTAINER_ID ls

  • 현재 돌아가고 있는 container 안에서 shell script 실행하기
    $ docker exec -ti CONTAINER_ID sh 
    • 앞에서 쓰지 않았던 -ti option에 대해 알아보자.
      • 먼저 어떤 옵션들이 있는지 확인하도록 하겠다.
        $ docker exec --help
      • 위에 보이다시피 -ti-i-t가 합쳐진 옵션이다.
      • -i : interactive option으로 shell script를 사용하려면 input을 받아야 하는데, localhost에서 입력한 input을 container에서도 사용하겠다는 뜻
      • -t : tty option으로 터미널 환경을 만들어서 shell script를 쓸 수 있도록 해줌

  • ls를 통해 확인한 폴더 구조에서 초록색 부분을 확인해보자.
    • cat : 현재 돌아가고 있는 화면을 shell에서 보여주는 것
$ cat docker-entrypoint.sh

  • 현재 실행중인 shell을 나가고 싶다면 아래의 명령어를 통해 나갈 수 있다.
$ exit

docker container 삭제하기

  • 아래의 명령어를 입력하면 된다.
4 docker rm CONTAINER_ID
  • 여기서 우리는 컨테이너가 실행되고 있는지를 확인해봐야 한다.
  • 아래 보이는 것과 같이 실행되고 있는 컨테이너는 삭제할 수 없다.
  • 따라서 삭제하고 싶은 컨테이너의 실행을 멈추고 삭제를 진행해야 한다.

docker 명령어 reference

docker 명령어 reference


flask 애플리케이션을 docker로 실행해보기

docker 이미지 생성하기

  • docker image를 만들기 위해서는 dockerfile이 필요하다.
    • dockerfile : docker image를 어떻게 생성할 것인지를 정의한 파일

dockerfile 생성

  • dockerfile을 아래와 같이 생성해보자.
FROM python:3.8

ADD requirements.txt .

RUN pip install -r requirements.txt

ADD templates ./templates/

ADD app.py .

CMD ["python", "app.py"]
  • 이미지를 생성할 때는 어떤 이미지를 먼저 생성할 것인지에 대한 순서가 중요하다. 각 순서에 대한 설명을 해보도록 하겠다.

    • FROM python:3.8 : 우리는 현재 flask를 사용할 것이고, flask는 python 환경에서 실행된다. 따라서 3.8 버전의 python을 dockerimage의 기본 이미지로 사용하기 위해 위와 같이 작성한다.

      • FROM : Docker image를 생성할 때 기본으로 사용할 base image를 적는 부분
      • 아래 사진은 위와 같은 의미이다.
    • ADD requirements.txt . : . 위치에 requirements.txt 파일을 저장한다.

      • ADD src dst : 호스트 머신에 있는 파일이나 폴더를, dst라는 위치에 저장
    • RUN pip install -r requirements.txt : shell에서 해당 커맨드를 실행해서 환경을 만들겠다.

      • RUN script : script를 실행한다.
    • CMD ["python", "app.py"] : ["python", "app.py"] 명령어를 기본적으로 실행한다. 즉 별다른 커맨드가 없다면 해당 커멘드가 자동적으로 실행되게 된다.

      • CMD : 생성된 docker image를 실행할 때 자동으로 실행되는 커맨드이다.

build 문법

  • 이미지를 만들기 전 build 문법에 대해 알아보도록 하겠다.
$ docker build [OPTIONS] PATH
  • build의 종류는 다음과 같다.
    • -t : image에 원하는 이름을 붙일 수 있다.
      • {image_name}:{tag} 의 형태로 사용하며, {tag}를 붙이지 않을경우 자동으로 latest가 됩니다.

이미지 생성

  • 이제 이미지를 만들어보도록 하겠다.
    • docker scan : 이미지에 보안 결함이 있는지 확인해주는 커맨드
    • . : docker build를 어느 위치에서 실행할 것인지 정의합니다. 이 위치에 따라 ADD 커맨드에서 호스트의 파일 위치를 사용하는게 바뀔 수 있습니다.
$ docker build .
  • 이미지를 생성할 때는 꼭 dockerfile이 있는 폴더 안에서 진행해야 한다.

이미지 확인

  • 이미지를 확인해보도록 하자.
$ docker images

  • 위의 사진을 보면 REPOSITORY와 TAG에 none 값이 들어있는 것을 볼 수 있다. 이렇게 되면 해당 이미지를 실행할 때 꼭 IMAGE_ID를 알아야 실행할 수 있는데 이것은 굉장히 비효율적이다.
  • 따라서 이미지의 이름을 주어 생성할 수 있다.
$ docker build -t docker-memo:version1 .
  • 결과 사진에서 확인해야 할 부분은 두 가지이다.
    • 이미 사진을 한 번 만들어보았기 때문의 사진 생성 속도가 엄청 빨라졌다.
      • 앞전은 3.7초가 걸린 반면 이번에는 0.1초가 걸렸다.
    • 사진의 이름이 나오게 되었다.

이미지의 레이어

  • 아래 코드를 통해 레이어를 확인할 수 있다.
$ docker history docker-memo:version1

  • 도커가 이미지를 생성할 때 맨 위에 있는 명령어, 즉 베이스 레이어에서부터 시작하여 명령어를 하나씩 실행할 때마다 우리가 원하는 이미지가 생성된다.
  • 이미지를 생성할 때 동일한 환경에서 진행하게 된다면, 아까 우리가 봤던 것과 같이 3.7초가 아닌 0.1초 만에 이미지를 생성할 수 있게 된다.

이미지 실행하기

  • 아래의 코드를 통해 실행할 수 있다.
$ docker run docker-memo:version1
$ docker run -d -p 5000:5000 docker-memo:version1

  • flask를 이미지로 만들었기 때문에 이미지를 실행하면 flask 서버가 실행되는 것을 볼 수 있다.
  • 이번에는 위와 같은 메세지가 나오지 않도록 백그라운드에서 실행시키도록 하겠다.
  • 브라우저에서 확인하면 서버가 돌아가고 있는 것을 볼 수 있다.

애플리케이션 업데이트

  • 도커 이미지는 한 번 생성이 된 후는 바뀌지 않는 것이 원칙이다.
  • 따라서 새로운 내용을 담기 위해서는 새로운 이미지를 생성해야 한다.
  • index.html의 내용을 다음과 같이 변경하고 새로운 이미지를 생성하도록 하자.
<body>
   <div class="wrap">
      <div class="jumbotron">
         <h1 class="display-4">ㄴㅐ꺼야 링크 메모장!</h1>
            <p class="lead">내용 바꿨어 ㅋ</p>
        
        ...
  • 아래의 명령어를 통해 새로운 이미지를 생성한다.
    • -t 옵션을 사용할 때 동일한 image_name:tag 를 사용할경우 override되므로 주의해야 한다.
    • 변경되지 않은 부분은 앞에 CACHED가 붙게 된다.
$ docker build . -t docker-memo:version2

  • 이미지가 잘 생성되었는지 확인해보자.
  • 이제 생성된 이미지를 실행해보도록 하겠다.
$ docker run -d -p 5000:5000 docker-memo:version2
  • 에러가 나는 이유는 이미 docker-memo:version1이 실행되고 있기 때문이다. 따라서 실행되고 있는 이미지를 끄고 실행해주어야 한다.
  • 브라우저에서 잘 실행되는 것을 볼 수 있다.

quiz 1

  • 요구사항
  • 나의 코드
$ docker run -d -p 80:5000 docker docker-memo:version2

  • localhost와 5000번 포트를 연결하였으니, 브라우저로 가 localhost만 쳐도 해당 페이지가 나오는지 확인해보도록 하겠다.

  • 아까 실습했던 화면이 나와버렸다. 당황하지 않고 아래의 순서에 따라 cache를 지워주면 된다.

    • f12를 눌러 devtool로 들어간다.
    • 네트워크 탭으로 들어가 캐시를 다 지워주고, 캐시 사용 중지를 선택해준다.
  • 변경했는데 안되서 이것저것 해보다보니 갑자기 변경이 되었다.

  • 이제 localhost를 브라우저에 입력해주면 사이트가 나온다.


애플리케이션 공유하기

docker registry

  • 이미지를 저장하고 분배하기 위한 저장소이다.
  • docker를 만든 회사에서 관리하는 제일 유명한 repository는 DockerHub이 있다.

    DockerHub

Docker Hub에 이미지 올리기

  • 먼저 회원가입을 진행한다.
  • 앱을 올리기 위해 repository를 생성한다.
    • public의 경우, 공짜로는 하나밖에 생성하지 못하다고 하니 유의!

Docker Hub에 이미지 올리기

  • 아래의 코드를 사용해 이미지를 올릴 수 있다.
    • 주의할 점은 docker image의 이름이 repository와 같아야 한다는 점이다.
      $ docker build -t wjdeorms27/docker-practice:1.0.0 .
  • 생성된 repository에 이미지를 올리기 위해 권한을 얻어야 한다.
$ docker login

# 후에 나오는 username, password에 치면 됩니다!

  • 이제 생성한 이미지를 올려보도록 하겠다.
$ docker push {user_id}/docker-practice:1.0.0

  • 이미지가 잘 올라갔는지 Docker Hub에 가서 확인해보도록 하겠다.

docker 이미지 삭제하기

  • 이미지가 공유될 수 있는지 확인하기 위해 로컬에 있는 이미지를 지워보도록 하겠다.
$ docker rmi IMAGE_ID:TAG

docker hub에서 이미지 받기

  • 아래의 코드를 통해 이미지를 받을 수 있다.
$ docker pull {user_id}/{repository_name}:{tag}
  • 하단의 사진을 보면 아까 지웠던 사진을 다시 받아온 것을 볼 수 있다.
  • 받아온 이미지를 실행시켜 보면 잘 실행되는 것을 볼 수 있다.
$ docker run -d -p 5000:5000 IMAGE_ID:TAG

  • 브라우저에서도 잘 돌아가는 것을 볼 수 있다.

docker image 생성하고 실행하기

  • 아래 코드 순서대로 진행하면 된다.
$ docker build .     <<< dockerfile이 있는 위치에서 해야함!
$ docker images
$ docker build -t homework:1.0.0 .
$ docker images     <<< image가 잘 생성되었는지 확인하기!!
$ docker run -d -p 5000:5000 homework:1.0.0
$ docker ps
profile
https://github.com/nikevapormax

0개의 댓글