최근에 사적으로 운영하는 서버에 docker를 도입하고 있습니다. 일주일정도 이렇게 저렇게 써보면서 획득한 팁을 공유하고자 합니다. 이 글에서는 docker의 기본적인 사용법에 대해서는 다루지 않을 것입니다.


https://docs.docker.com/userguide/

http://forum.docker.co.kr/t/docker-docker-howto/68/5

http://blog.nacyot.com/articles/2014-01-27-easy-deploy-with-docker/


위 사이트들에 제가 할 수 있는 것보다 훨씬 더 정리를 잘 해두었기 때문입니다.


1. Container VS Image

 처음에 docker를 접하게 되면 container와 image의 개념이 정립되지 않아 혼동이 발생합니다. 


Image가 rootfs라면 container는 rootfs를 ramfs에 압축을 푼 상태라고 볼 수 있습니다. 즉, image는 지속적으로 보존되지만, container는 임시로 저장된다고 생각하시는게 편합니다. 


물론 container도 stop이후에 start하면 이전 상태의 파일들을 그대로 보존되어있지만, 저는 위의 개념으로 정리를 했습니다. 즉, "image를 사용하여 언제든지 새로운 container를 생성하여 서비스를 실행한다"고 생각하시면 편합니다.


2. Foreground

 보통의 ubuntu에서의 서비스는 background로 동작합니다. 그래야 foreground에서는 원하는 작업을 할 수 있기 때문이죠. 하지만 docker에서는 그렇게 하면 안됩니다.


만약 docker에서 container를 하나 만들어 "service apache2 start"라는 명령을 수행하게 되면 그 container는 저 명령을 수행한 후 종료해버립니다. 즉, apache2 서비스를 계속 실행하지 못하는 상황이 되는거죠.


따라서 docker에서는 "apache2 -DFOREGROUND" 명령으로 프로세스가 background로 가지 않도록 해주어야지 프로세스가 계속 실행됩니다.


3. RUN xx && yy && zz

Dockerfile을 접하시다보면 위와 같이 &&로 주루룩 연결된 구문을 볼 수 있습니다. 저도 처음에는 따로따로 구분 해두는 것이 가독성이 좋지 않을까.. 라고 생각하면서 모두다 해체하는 작업을 했습니다.


하지만 괜히 저렇게 하는 것이 아닙니다. Dockerfile으로 image를 build할 때는 각각의 스탭마다 스냅샷이 생성됩니다.

만약 

RUN curl -SLO "http://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.gz" 
RUN curl -SLO "http://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" 
RUN gpg --verify SHASUMS256.txt.asc 
RUN grep " node-v$NODE_VERSION-linux-x64.tar.gz$" SHASUMS256.txt.asc | sha256sum -c - 
RUN tar -xzf "node-v$NODE_VERSION-linux-x64.tar.gz" -C /usr/local --strip-components=1 
RUN rm "node-v$NODE_VERSION-linux-x64.tar.gz" SHASUMS256.txt.asc


위와 같이 한다면 각 스탭마다 캐쉬가 되는 장점은 있습니다만, 디스크 공간을 많이 차지하게 됩니다.


하지만, 


RUN curl -SLO "http://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.gz" \
        && curl -SLO "http://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \
        && gpg --verify SHASUMS256.txt.asc \
        && grep " node-v$NODE_VERSION-linux-x64.tar.gz\$" SHASUMS256.txt.asc | sha256sum -c - \
        && tar -xzf "node-v$NODE_VERSION-linux-x64.tar.gz" -C /usr/local --strip-components=1 \
        && rm "node-v$NODE_VERSION-linux-x64.tar.gz" SHASUMS256.txt.asc

위와 같이 한다면 이것이 하나의 스탭으로 되어 디스크 공간을 절약할 수 있게 됩니다.


4. Logging

 보통의 ubuntu 서비스들은 logging을 /var/log 폴더에 위치하도록 설정합니다. 하지만 이것 역시 docker에서는 바람직하지 않습니다. 왜냐하면 위에서 말했다시피 container의 자료들은 임시적이라고 생각하셔야한다고 했습니다. 따라서 container 실행 중 생성되는 자료들은 언제라도 사라질 수 있다고 봐야하기 때문에 위의 일반적인 방식은 바람직하지 않다고 하는 것입니다.


Docker의 container의 logging은 console로 하시는 것이 가장 좋습니다. 그렇게 하면 "docker logs [-f] <container>" 명령으로 로그를 확인할 수 있습니다.


만약 분석을 위해 반드시 파일로 저장해야한다면 뒤에 설명할 volume container를 사용하도록 합시다.


5. Volume container

위에서의 연속이 되는 내용입니다. "만약 container에서 변경되는 내용이 유지가 되어야한다면, 그리고 만약 여러개의 container가 그 변경사항들을 공유해야한다면?" 이라는 의문이 생길 때 사용할 수 있는 것이 volume container입니다.


Dockerfile에 기술할 수 있는 내용으로 

VOLUME ["/app"]

이렇게 해두면 마치 nfs server를 운영할 때 exportfs에 설정하듯이, /app 폴더는 다른 container에서 마운트가 가능해집니다.


volume container로 사용할 container는 별다른 명령이 필요가 없습니다. 상태(실행중, 종료)와 무관하게 설정된 폴더를 마운트 할 수 있기 때문이죠.


보관의 문제도 있지만, 백업을 위해서라도 volume container의 사용은 필수입니다.


만약 tingodb나 sqlite3같은 파일기반 데이터베이스를 사용하여 운영 중인 container가 있다고 가정합시다. 해당 서비스를 업그레이드 해야한다면 저 데이터베이스를 백업 받기가 쉽지 않습니다.

하지만 volume container에 데이터베이스를 보관하고 있다면 얘기가 다릅니다. 운영 중인 container와 별개로 volume container를 마운트하는 busybox container를 생성하여 tar로 압축하면 간단하게 백업을 받을 수 있습니다.


docker run -i -t --rm --volumes-from <volume-container> -v $(pwd)/backup:/backup busybox tar cvf /backup/backup.tar /var/www /etc/apache2
위의 내용은 제가 아파치 서비스에 연결된 volume container를 백업받는 스크립트의 내용입니다.


6. MySQL server

지금 MySQL server도 docker로 이관을 준비 중에 있습니다만, stop에서 문제가 있어 host pc에서 돌려야겠다고 다시 마음을 고쳐먹고 있습니다.


Database 특성상 서비스의 중단은 매우 중요한 역할입니다. 하지만 docker stop mysql-server로 중단했을 경우 강제로 종료되어버려 다시 시작할 때 비정상 종료에 대한 복구를 실행하는 과정이 수행되는 것을 확인했습니다.


자칫 데이터를 쓰고 있는 중에 강제 종료가 된다면 사태가 심각해질 수도 있기 때문에 docker로 운영하기에는 적합하지 않다고 판단했습니다.


MySQL server 뿐만 아니라 종료할 때 중요한 작업을 하는 서비스라면 docker로 운영할 때 신중해야할 필요가 있다고 생각이 되네요.



이상 1주일 정도 docker를 사용하면서 찾아보고 겪어봤던 것들을 간략하게 정리해봤습니다. 글로 적은 것보다 훨씬 더 많은 것을 경험했었지만, 중요하다고 생각되는 부분만 정리를 했습니다.


Docker는 확실히 매력적인 배포시스템입니다. 보통 리눅스 서버를 운영하다보면 이것저것 덕지덕지 깔다보면 나중에 서버를 이전한다거나 ubuntu 버전을 올릴 때 매우 고생을 하게 되는데, docker를 사용한다면 이런 고민에서 벗어날 수 있을 것 같네요.