기본 콘텐츠로 건너뛰기

[Docker] Docker 사용법

 https://sddev.tistory.com/124

위 링크 내용을 가져와서 내용 습득을 위해 다시 한번 정리한 것입니다.


Docker 사용법


 # Docker 개요


개발 환경 구성에 대한 문서를 계속 업데이트한다면 이런 문제가 최소화되겠지만, 

상상하는 것만으로도 진이 빠지는 일인 건 분명




# Docker 적용하기


1. local에서 프로젝트 폴더를 생성하고자 하는 경로에서, git clone해오거나, usb에서 프로젝트 폴더를 복사


2. 프로젝트 루트 디렉토리에서 도커 이미지 빌드 및 생성

[cmd] cd 프로젝트폴더경로 

[cmd] docker build -t (도커_이미지_이름)

(ex) docker build -t sdweb-docker-img


// sdweb-docker-img라는 도커 이미지가 생성됨

// 아래의 명령어로 생성된 docker 조회 가능


[cmd] docker image ls | grep (검색어)

(ex) docker image ls | grep sdweb-docker-img


3. 프로젝트 앱 컨테이너 실행 (2번의 이미지를 컨테이너로 실행)

[cmd] docker run -it --rm -p 8000:8000 sdweb-docker-img ./실행파일..?

// 데이터 베이스가 연결되어 있지 않기 때문에 에러남



4. 데이터베이스 컨테이너 실행

[cmd] docker run -it --rm (db도커이미지명)

(ex) docker run -it --rm protgres

// 기본적으로 도커 컨테이너들은 각각 격리된 환경에서 실행

// 다시 말해, 별도의 옵션을 지정하지 않으면 다른 컨테이너의 존재를 알 수 없음. 각각 실행만 시키면 무의미



5. 데이터베이스 컨테이너 연결

- 데이터베이스 컨테이너를 실행하면서 컨테이너 이름을 붙이고(db라고 하죠),

- 앱 컨테이너를 실행할 때 db 컨테이너를 연결해 줍니다.

docker run --rm(-it 노테이션 삭제함으로써 데몬 형태로 컨테이너 실행)\

    --name db(db 컨테이너 이름 붙임) \

    -e POSTGRES_DB=djangosample(-e 노테이션으로 컨테이너 내 환경변수설정) \

    -e POSTGRES_USER=sampleuser \

    -e POSTGRES_PASSWORD=samplesecret \

    postgres(db도커이미지명)


실행 명령

docker run --rm --name db -e POSTGRES_DB=djangosample -e POSTGRES_USER=sampleuser -e POSTGRES_PASSWORD=samplesecret postgres


// 도커 허브의 공식 포스트그레SQL 저장소에 가보면 설정할 수 있는 환경 변수 종류가 존재

// 여기서 설정한 사용자 이름이나 비밀번호, 데이터베이스 이름 같은 환경변수들은  

sdweb프로젝트폴더/settings.ts 파일 안에 설정해 둔 기본값들이다.

(프로젝트가 알고 있는 값)




6. 앱 컨테이너 실행 및 데이터베이스 컨테이너 연결(link)

docker run -it --rm \

    -p 8000:8000(앞의 8000은 도커를 설치한 호스트의 8000포트를, 컨테이너의 8000번 포트에 연결한다) \

    --link db(db 컨테이너 이름 붙였던 것,--link: 참조할 다른 컨테이너를 지정) \

    -e DJANGO_DB_HOST=db \

    -e DJANGO_DEBUG=True \

    sdweb-docker-img \

    ./manage.py runserver 0:8000(마지막 줄은 프로젝트 속성에 따라 실행 명령어 달라질 듯)


실행 명령

docker run -it --rm -p 8000:8000 --link db -e DJANGO_DB_HOST=db -e DJANGO_DEBUG=True sdweb-docker-img ./manage.py runserver 0:8000


// 연동도 완료되지만, 소스코드를 변경해도, 결과가 반영이 안되는 문제가 존재

// 프로젝트 폴더에 생성된 Dockerfile을 분석해 보면 10행의 ADD ./sdweb /app/sdweb/ 이라는 명령어를 통해 

// 컨테이너 밖의 소스를 컨테이너 안에 추가함으로써, 격리되어 더이상 소스코드 변경에 영향 받지 않음

// 수정할 소스 코드의 디렉터리를 앱 컨테이너 내부의 소스 코드와 연결하여, 

// 코드를 바꿀 때마다 컨테이너 속 코드도 바뀌게 하는 작업이 필요




7. 코드 변경이 실시간으로 반영되게 하기

// 기존 앱컨테이너 종료(Ctrl + C)

docker run -it --rm \

    -p 8000:8000 \

    --link db \

    -e DJANGO_DB_HOST=db \

    -e DJANGO_DEBUG=True \

    --volume=$(pwd):/app/(--volume: 이 옵션을 사용하여 로컬 디렉터리의 특정 경로를 컨테이너 내부로 마운트, ($(pwd)는 이 명령을 실행하는 현재 디렉터리의 절대 경로, app폴더는 로컬디렉토리에서 격리된 컨테이너로 마운트할 수 있게 된다.) \

    sdweb-docker-img \

    ./manage.py runserver 0:8000



8. 컨테이너 종료하기

// 앱 컨테이너 종료(Ctrl + C)

// 데이터베이스 컨테이너 종료

[cmd] docker stop db(기존에 지정했던 이름)




9. 데이터베이스 데이터 보존

// 컨테이너 실행시 --rm 옵션을 지정할 경우, 데이터베이스 컨테이너가 종료와 함꼐 사라짐

// 그와 동시에 컨테이너 내부에 쌓였던 데이터베이스 데이터들도 모두 삭제(깔끔하지만, 개발용 데이터 매번 쌓기 귀찮)

// 데이터베이스가 데이터를 저장할 때 파일 시스템을 사용한다는 점을 생각해보면, 이를 해결할 때도 역시 --volume 옵션을 사용

$ mkdir -p ./docker/data //프로젝트 경로 내에서 'docker/data'라는 폴더 생성(이름 임의 지정 가능)

$ docker run -it --rm \

    --name db \

    -e POSTGRES_DB=djangosample \

    -e POSTGRES_USER=sampleuser \

    -e POSTGRES_PASSWORD=samplesecret \

    --volume=$(pwd)/docker/data:/var/lib/postgresql/data \


// 가운데 ':' 기호를 유의

// 데이터베이스 컨테이너 내부의 디렉터리(/var/lib/postgresql/data)를 

// 로컬 컴퓨터의 디렉터리($(pwd)/docker/data)로 연결

    postgres:

// 이제 데이터베이스가 데이터를 저장할 파일 시스템으로 로컬 컴퓨터의  $(pwd)/docker/data 폴더를 사용




# 정리(순서 유의)

1. 데이터베이스 컨테이너 실행


docker run -it --rm \

    --name db \

    -e POSTGRES_DB=djangosample \

    -e POSTGRES_USER=sampleuser \

    -e POSTGRES_PASSWORD=samplesecret \

    --volume=$(pwd)/docker/data:/var/lib/postgresql/data \

    postgres

실행

docker run -it --rm --name db -e POSTGRES_DB=djangosample -e POSTGRES_USER=sampleuser e POSTGRES_PASSWORD=samplesecret --volume=$(pwd)/docker/data:/var/lib/postgresql/data postgres



2. 새 터미널 창에서 앱 컨테이너 실행


docker run -it --rm \

    -p 8000:8000 \

    --link db \

    -e DJANGO_DB_HOST=db \

    -e DJANGO_DEBUG=True \

    --volume=$(pwd):/app/ \

    django-sample \

    ./manage.py runserver 0:8000


// 위의 두개 명령어만으로도, DB와 잘 연결되고, 소스코드 변경하면 개발서버가 알아서 재시작

// 컨테이너를 종료해도 DB가 로컬에 저장




# Docker-compose로 개발 환경 구성하기


컨테이너 실행에 필요한 옵션을 docker-compose.yml이라는 파일에 적어두고, 컨테이너 간 실행 순서와 의존성을 관리하자!


1. docker-compose.yml 파일 만들기

- 장황한 도커 실행 옵션을 미리 적어둔 문서

- 프로젝트 루트에 파일을 만든다.


version: '3' // 파일 규격(규격에 따라 지원하는 옵션 달라짐, 3으로 시작하는 최신버전 사용)


services:    // 해당 항목 밑에 실행하려는 컨테이너 정의(containers == services)

  db:        // postgres docker이미지 서비스의 이름을 db로 지정하였음

    image: postgres // 해당 서비스(db라는 컨테이너)가 사용할 도커이미지명

                    // postgres 명칭은  dockerhub의 공식 postgres 이미지     

    volumes:        // 컨테이너 내부 폴더와 로컬 폴더 사이의 마운트 관계 지정(격리를 푸는 연결 통로)

      - ./docker/data:/var/lib/postgresql/data // './'은 로컬의 루트프로젝트 폴더경로

                    // 컨테이너 내 var/lib/portgresql/data를 로컬 내 projectRoot/docker/data로 마운트

    environment:    // 컨테이너 내부의 환경변수 지정(docker run 명령어의 -e 옵션과 대응)

      - POSTGRES_DB=sampledb

      - POSTGRES_USER=sampleuser

      - POSTGRES_PASSWORD=samplesecret

      - POSTGRES_INITDB_ARGS=--encoding=UTF-8 // 데이터베이스 서버의 인코딩 설정

  sdweb:            // 앱 서비스의 이름을 sdweb으로 지정

    build:          // db 컨테이너 서비스와 다르게 앱은 특정 이미지(redis, postgres...) 대신 build 옵션을 추가

      context: .    // docker build 명령을 실행할 디렉토리 경로

      dockerfile: ./compose/django/Dockerfile-dev //<개발용> 도커이미지를 빌드하는데 사용할 Dockerfile 지정

                                                  //개발용 Dockerfile-dev에서는 소스코드를 앱 컨테이너에 넣지 않음(로컬 소스가 실시간 반영이 안되므로)

    environment:    // 앱 서비스의 환경 변수로 지정(DB 접속정보는 db 서비스에 입력한 것과 동일해야함)

      - DJANGO_DEBUG=True        // 각 값들을 프로젝트 소스 내의 설정관련된 부분에서 불러와 사용

      - DJANGO_DB_HOST=db

      - DJANGO_DB_PORT=5432

      - DJANGO_DB_NAME=sampledb

      - DJANGO_DB_USERNAME=sampleuser

      - DJANGO_DB_PASSWORD=samplesecret

      - DJANGO_SECRET_KEY=dev_secret_key

    ports:          // docker run 명령어의 -p 옵션에 해당하는 부분(포트 지정)

      - "8000:8000"

    command:        // 앱 컨테이너를 실행시 가장 마지막에 적었던 명령어 부분

      - python manage.py runserver 0:8000

    volumes:        // docker run 명령어의 -volumes 옵션에 해당하는 부분(마운트 지정)

      - ./:/app/    // 컨테이너 내 app 폴더를 로컬 내 루트 프로젝트 폴더로 마운트

^z      


# docker-compose 명령어 실행


[yml파일이 있는루트 프로젝트 폴더경로] docker-compose up -d

// http://127.0.0.1:8000에 접속해보면 개발 서버가 잘 작동함을 확인 가능

// up -d : yml 파일 내용에 따라 이미지를 BUILD하고, 서비스(컨테이너)를 실행합니다.

// -d: 서비스 실행 후 콘솔로 빠져나옵니다.

// --force-recreate: 컨테이너를 지우고 새로 만듭니다.

// --build: 서비스(컨테이너) 시작 전 이미지를 새로 만듭니다.

(dock run 명령어로 자동생성되는 운영환경설정기록인 Dockfile로 build하여 동일한 이미지를 만든다.)

(이미지를 통해 격리된 컨테이너를 생성한다.)


1. 서비스를 띄울 네트워크 설정

2. 필요한 볼륨 생성(혹은 이미 존재하는 볼륨과 연결)

3. 필요한 이미지 풀(pull)

4. 필요한 이미지 빌드(build)

5. 서비스 의존성에 따라 서비스 실행




[루트 프로젝트 폴더경로] docker-compose ps : 현재 환경에서 실행중인 각 서비스의 상태 조회

[루트 프로젝트 폴더경로] docker-compose stop : 현재 환경에서 실행중인 서비스를 멈춥니다.

[루트 프로젝트 폴더경로] docker-compose start : 현재 환경에서 실행중인 서비스를 시작합니다.

[루트 프로젝트 폴더경로] docker-compose down --volume: 현재 환경에서 컨테이너, 네트워크 삭제, 또는 볼륨까지도 삭제

[루트 프로젝트 폴더경로] docker-compose exec (명령어) : 실행 중인 컨테이너에서 명령어 실행

[루트 프로젝트 폴더경로] docker-compose logs (서비스,컨테이너명) : 서비스명 없으면 모든 서비스의 로그

-f: 지금까지 쌓인 로그를 다 보여준 후에도 셸로 빠져나오지 않고, 로그가 쌓일 때마다 계속해서 출력합니다.




# 단축명령어 적용하기(맥 또는 리눅스)


~/.bashrc나 ~/.zshrc 파일 상에 alias 적용


alias dco='docker-compose'

alias dcb='docker-compose build'

alias dce='docker-compose exec'

alias dcps='docker-compose ps'

alias dcr='docker-compose run'

alias dcup='docker-compose up'

alias dcdn='docker-compose down'

alias dcl='docker-compose logs'

alias dclf='docker-compose logs -f'


# docker-compose 버전 차이


- 2 : links 항목을 통해 연결할 컨테이너 지정해주어야 했음

- 3 : 동일 네트워크 안에 있는 서비스끼리 서로 통신 가능




# tip


1. docker-compose.yml 수정 후, 서비스들에 적용하길 원하는 경우

docker-compose.yml 파일을 수정하고 이를 서비스에 적용하려면 서비스를 멈추고(stop), 서비스를 지우고(rm), 

서비스를 시작해야(up) 합니다.


하지만 up 명령만 실행해도, (현재 실행 중인 서비스 설정과 달라진 부분이 있다면) 알아서 컨테이너를 재생성하고 

서비스를 재시작해줍니다.*


2. Dockerfile-dev 파일 수정 후, 서비스들에 적용하길 원하는 경우

up 명령에 다음과 같이 --build 옵션을 넣으면 알아서 이미지를 새로 만들고 서비스를 재시작합니다


docker-compose up -d --build [서비스_이름]


3. Dockerfile-dev도 중요


개발용 이미지를 담당하는 Dockerfile-dev 파일과 배포용 이미지를 담당하는 Dockerfile 파일이 따로 존재한다는 점을 

꼭 기억해야 합니다. 간혹 Dockerfile만 고치면서 개발 환경에서 ‘외않돼?’라고 생각한 경우가 있습니다.


4. 데이터베이스 내용도 지우고 싶을 때


docker-compose down --volume : 깔끔하게 초기화 된다.




# Dockfile-dev에 관하여(불필요한 운영환경설정 명령어 생략)


FROM python:3


RUN apt-get update && apt-get -y install \

    libpq-dev


WORKDIR /app

ADD    ./requirements.txt   /app/

RUN    pip install -r requirements.txt


# ADD    ./djangosample   /app/djangosample/ 

// 해당 명령어 때문에, 로컬 프로젝트 소스 폴더와 컨테이너 내 소스폴더의 격리가 시작되는 것!(개발 중에는 필요 없음)

# ADD    ./manage.py      /app/


# CMD ["python", "manage.py", "runserver", "0:8000"]


// CMD: 도커 컴포즈의 command 속성으로 관리하는 편이 더 쉽기 때문에 생략





# 영구 db 저장소를 로컬에 맡기지 않고, Docker에 맡기기


1. Docker 볼륨을 생성한다.

볼륨은 도커가 관리하는 가상 디스크라고 생각


2. db 서비스 선언부 안에 volumes 항목을 넣고  

- 가상디스크_이름 : 컨테이너_속_디렉터리처럼 지정


3. 이후로는 모든 데이터베이스 데이터가  django_sample_db_dev 볼륨에 저장됨


version: '3'


# 변경 부분!

volumes:                   //Docker 가상 디스크 생성

  django_sample_db_dev: {}


services:

  db:

    image: postgres

    volumes:

      # 여기도!

      - django_sample_db_dev:/var/lib/postgresql/data // 가상 디스크로 마운트

    environment:

      ...


4. 가상 디스크 조회하기

docker volume ls


5. 가상 디스크 삭제하기

docker volume rm django_sample_db_dev 



# 디버깅

1. 앱 서버가 데이터베이스를 못찾는 경우

- 첫 실행시 데이터베이스가 실행된 후 초기화 전에 앱서버가 실행되서 발생

- 가장 간단한 해결 방법은 서비스를 중지하고 다시 실행하는 것이지만 근본적인 해결책은 아님

- 이를 위해 wait-for-it.sh이라는 셸 스크립트를 사용

- 이 스크립트를 도커 이미지 안에 넣고, 이미지 실행 명령 앞에 붙여주면 됩니다.

./compose/django/Dockerfile-dev 파일의 마지막 부분에 다음 내용을 추가


ADD    https://raw.githubusercontent.com/vishnubob/wait-for-it/master/wait-for-it.sh /


- docker-compose.yml 내 수정


services:

  django:

    command:

      - bash

      - -c

      - |

        /wait-for-it.sh db:5432 -t 10 // db 서비스의 5432 포트가 사용 가능할 때까지 기다린 후 앱 서버 실행

        python manage.py runserver 0:8000



# 출처

https://www.44bits.io/ko/post/almost-perfect-development-environment-with-docker-and-docker-compose#%EB%8F%84%EC%BB%A4%EA%B0%80-%EB%B3%84%EB%A1%9C-%ED%8E%B8%ED%95%98%EC%A7%84-%EC%95%8A%EB%84%A4%EC%9A%94



 


 


# Docker : 서버 인프라를 VM 기반에서 Container 중심으로


2013년 등장한 도커[Docker]는 인프라 세계를 컨테이너[Container] 세상으로 바꿔버렸습니다. 수많은 애플리케이션이 컨테이너로 배포되고 도커파일을 만들어 이미지를 빌드하고 컨테이너를 배포하는 게 흔한 개발 프로세스가 되었습니다


댓글

이 블로그의 인기 게시물

이클립스 실행 오류와 eclipse.ini 수정

1. 실행시 Java was started but returned exit code=13 에러가 날때 --> Win7 64bit를 사용중인데, 이 오류가 발생하고 있었습니다. 제가 자바도 이클립스용도 32비트 버젼을 사용중이었는데, 자바만 64비트용으로 설치를 했더니, 생긴 문제였습니다. 이클립스 64비트를 설치하시면 해결됩니다. 2.이클립스 폴더내 eclipse.ini 기본값(보통 아래 처럼 되어 있습니다.) -startup plugins/org.eclipse.equinox.launcher_1.1.0.v20100507.jar --launcher.library plugins/org.eclipse.equinox.launcher.win32.win32.x86_1.1.1.R36x_v20100810 -product org.eclipse.epp.package.jee.product --launcher.defaultAction openFile --launcher.XXMaxPermSize 256M -showsplash org.eclipse.platform --launcher.XXMaxPermSize 256m --launcher.defaultAction openFile -vmargs -Dosgi.requiredJavaVersion=1.5 -Xms40m -Xmx512m 3.실행하자 마자 javaw.exe 찾기 실패시  --> jdk가 설치된 경로(javaw.exe가 있는 경로)를 추가해준다. 맨 아래쪽에 삽입하니 안되더군요.(왜죠?) -vmargs 윗부분에 삽입했습니다. 다른 블로그님 들 글에선 open 위쪽에 쓰니 괜찮다는 글도 있으니 참고하세요. -vm c:\Program Files\java\jre6\bin\javaw.exe 4.이클립스 속도 향상을 위한 추가값 출처:  http://blog.naver.com/sungback/90097516641 검색도중 이클립스 속도 향상 정보를 발

[c#.net] WPF 사용 중 xaml관련 실행시 오류 와 대처 방법

wpf 사용 중 xaml관련 실행시 오류 가 발생해서 자그마치 2일을 소비 했다..--;; 오류 내용은 아래와 같다. ================================== 'System.Windows.Markup.XamlParseException' 형식의 첫째 예외가 PresentationFrameWork.dll에서 발생했습니다. 추가 정보: '지정된 바인딩 제약 조건과 일치하는 'PapaZone.MainWindow' 형식에 대한 생성자 호출에서 예외가 throw 되었습니다.' 줄 번호 '21' 및 줄 위치 '9' 이 예외에 대한 처리기가 있으면 프로그램을 안전하게 계속할 수 있습니다. [] 이 예외 형식이 throw되면 중단 ================================== 위 Xaml 오류 메세지만으로는 내용 추적 불가하여, 도대체 뭔가 했다. 검색해도 뚜렷한 답변은 없었지만, 여러가지 의견을 종합해 보면 아래와 같다. 1. xmlns 관련 파일 과 관련된 파일 로딩 실패 이거나, 2. 신규로 추가된 namespace 에 속한 태그 사용시 오류로 판단되어 태그 하나씩 삽입하며 테스트 해봐야 한다고 함. 해결한 지금에 원인을 보면, xaml 에서 clr-namespace 로 추가된 항목들이 로딩에 실패해서 발생한 것이며, 추가된 항목은 있었으나, 이것과 연결된 파일이 없어서 로딩되지 않는 것이 문제였다. 오늘도 즐거운 하루~~

[MSSQL] SQL Server 에 원격 접속을 못하는 경우 조치 방법

[MSSQL] SQL Server 에 원격 접속을 못하는 경우 조치 방법 내부 오류 추적 결과 다음과 같이 나옴. [Microsoft][ODBC Driver 13 for SQL Server]TCP Provider: 대상 컴퓨터에서 연결을 거부했으므로 연결하지 못했습니다. SqlState : 08001, NativeError : 10061 오류 원인과 처리 1.SQL 서버 로그인 계정 틀린 경우 -> A.SQL Managerment Studio에서 사용할 DB 접속 '로그인' 사용할 계정의 아이디/암호 확인 2.TCP/IP 접속 권한이 없는 경우 -> A.SQL Server 구성 관리자를 실행에서 TCP/IP 허용 되어 있는지 확인 B. 서비스 포트 값이 (보통 1433) 맞는지 확인 C. 외부에서 접속하는 경우에는 방화벽 허용 되엉 있는지 확인 C. 서비스 재시작 3.Windows 인증 모드만 허용 인 경우 -> A.SQL Managerment Studio에서 사용할 DB 접속하고, 우클릭 하여 속성 정보 확인해서 B.연결에서 인증모드 '로그인' 사용할 계정의 아이디/암호 확인 4.'exec Sp_ReadErrorLog' 명령어를 사용해서, 로그인 실패 로그를 확인해서 원인을 분석한다.