도커 호스트,호스트OS, 도커 서버 하나 이상의 도커 컨테이너를 실행하는 리눅스 머신 도커 데몬,도커 서버 프로세스 도커 클라이언트의 요청을 받아 도커 컨테이너를 실행/종료/관리 Dockerfile 베이스 이미지에 넣을 패키지 일람을 정의해놓는 파일 도커 이미지 이미지도커 컨테이너의 초기 상태를 기록한 파일. 파일시스템을 효율적으로 압축한 파일이다(iso 파일처럼). 도커 이미지는 git과 같은 버저닝(commit),상속(branch),원격보관(push),내려받기(pull)을 가짐 도커 클라이언트 docker 명령을 실행하는 머신,도커 호스트와 다른 머실일 수 있고,리눅스가 아니어도 됨. 도커 허브 도커 이미지를 올리고/받고/검색할 수 있는 공식 도커 이미지 저장소(repository) 베이스 이미지 기본적인 OS인스톨 이미지(Docker hub에 올라가 있음) 컨테이너 도커 이미지를 실행한 상태 하나의 프로세스라고도 말할 수 있음
베이스 이미지 docker run docker build Host OS 철수는 xx영화가 너무 재밌어서 xx영화가 들어있는 cd를 책상옆에 있는 cd보관함에 넣었습니다. CD보관함=Docker repository(docker hub,aws ecr) CD보관함에 넣다=docker push docker push
도입됨 • 2000년 FreeBSD 4.0에서 FreeBSD Jail가 등장 • 일반 유저에게 루트 권한을 주기 위한 고안됨(이 시절은 그런게 안 됐었다함) • Solaris Containers • 가장 docker같은놈(패키징화해서 소스 빌드 생략!) • 2008년 리눅스 커널에 Linux cgroups가 merge됨 • LXC 구획화,분리화 라는 말을 쓰지 않고 컨테이너라는 용어가 나오기 시작 • Docker 2014년 등장 LXC는 관심밖으로 멀어짐
보유가능 • 커널의 Control Group(cgroups) 기능을 통해 CPU도 메모리도, 디스크와 네트웍자원까지 할당할 수 있도록 했고, 커널의 Namespace isolation(혹은 namespaces)이란 기능으로 프로세스트리와 사용자계정, fs까지도 격리 시킴 • 리눅스 커널 즉 호스트OS를 공유 • 이동 가능한 경량화된 가상화 기반의 운영체제 • Go언어로 만들어짐
좋음 • 앱을 클라우드 기반 서비스 형태로 판다고 할 때 개발, 테스트, 운영에 이르는 프로세스가 대폭 단축됨 • 수많은 고객에게 별도의 애플리케이션 이용환경을 할당하고 업데이트를 지속해야 하는 SaaS와 PaaS 같은 클라우드 서비스 진영에서 많이 활용 • 하드웨어와 운영비용을 연간 수십만에서 수백만 달러까지 절감 가능 • 결론.규모가 크면 클수록 쓰면 좋음
development beta staging productoon shared memcached redis elasticsearch td-agent mysql base Dockerfile docker- compose.yml Middleware layer안의 각 하위 디렉토리에는 rails.env layer가 존재(unicorn외에는 생략) Mysql의 경우 development환경빼고 aws RDS를 쓰므로 development디렉토리만 존재
nginx unicorn development beta staging productoon shared memcached redis elasticsearch td-agent mysql Dockerfile docker- compose.yml Rails_root 전체 리포지토리 최상위 디렉토리입니다.
nginx unicorn development beta staging productoon shared memcached redis elasticsearch td-agent mysql Dockerfile docker- compose.yml File name description docker-compose.yml 복수의 컨테이너를 간편히 실행 (주로development환경에서 사용) Dockerfile docker build시 사용 최상위 디렉토리에 있는 docker관련 디렉토리 입니다. Docker관련파일은 development환경에서 쓰이는 Dockerfile,docker-compose.yml뿐입니다.
nginx unicorn development beta staging productoon shared memcached redis elasticsearch td-agent mysql base Dockerfile docker- compose.yml Docker 디렉토리안에는 사용되어지는 미들웨어가 디렉토리별로 존재합니다. 그외에 미들웨어의 상위 docker image에 해당하는 소스들을 관리하는 base디렉토리가 있습니다.(base디렉토리에 대해서는 나중에 설명)
nginx unicorn development beta staging productoon shared memcached redis elasticsearch td-agent mysql base Dockerfile docker- compose.yml Middleware디렉토리 하위는 환경별로 디렉토리로 나누어집니다. 그 외에 각환경에서 공통적으로 사용되어지는 파일이 있는 shared디렉토리가 있습니다.
{development staging, production} files set_env.sh set._key.sh run_sh.sh 그외 도커 컨테이너에서 필요한 파일 test Dockerfile build_docker.s h run_docker.sh push_docker.s h deploy 파일명 설명 Dockerfile docker build시 사용 Files디렉토리 docker컨테이너안에서 사용할 파일(Dockerfile안에서 files통째로 ADD함) build_docker.sh docker build시 사용하는 명령어를 정의 run_docker.sh docker build로 만들어진 도커이미지를 run할때 사용. 주로 컨테이너 동작 테스트시 사용(serverspec) Push_docker.sh Build,test가 끝난 docker이미지를 aws ecr에 push deploy디렉토리 디플로이 관련 설정파일(Task Definition file등)을 정의
첨부파일 Docker_build_root Rails_env {development staging, production} files set_env.sh set._key.sh run_sh.sh 그외 도커 컨테이너에서 필요한 파일 test Dockerfile build_docker.s h run_docker.sh push_docker.s h deploy 파일명 설명 set_env.sh S3에서 환경변수를 취득 set_key.sh S3에서 ssh key를 취득 run_sh.sh 도커 컨테이너를 올리기전에 실행하고 싶은 shellscript파일 정의 build_docker.sh docker build시 사용하는 명령어를 정의 Other_files 그외 도커 컨테이너 안에서 필요한 파일들
staging, production} files set_env.sh set._key.sh run_sh.sh 그외 도커 컨테이너에서 필요한 파일 Dockerfile build_docker.sh run_docker.sh push_docker.sh deploy Docker build시 사용되는 커맨드는 전부 build_docker.sh에 정의
hub의 automation build 기능을 쓰려니 각 이미지별로 리포지토리를 만들어야 되서 리포지토리의 낭비가심하고 관리가 귀찮.. • 하나의 리포지토리 안에서 복수의 automation build 기능을 구현하고 싶음 • 각 환경별 branch에 git push만 해주면 build,push,test,deploy까지 전부 알아서 해주는 시스템을 만들고 싶음
Build 를 위해 circleCI를 이용 • Docker디렉토리 구조에서 설명했듯이 각 Middleware별로 docker build를 해주는build_docker.sh파일이 존재함 • circleCI안에서 git diff커맨드를 사용해서 해당Middleware하위 디렉토리에 있는 파일이 갱신되었을때만 해당 레이어의 build_docker.sh 파일을 실행시키도록 함
• 현재 엔지니어 구성은 개발자 10명,인프라 엔지니어 1명인 상황 • P.R횟수는 절대적으로 rails관련이 많음 • circleCI상에서 실행되는 rails관련 rspec테스트만 20분이 걸림 • 거기에 docker build,run 시켜서 그 위에서 rspec을 실행하게 되면 테스트에 걸리는 시간이 더 늘어나게 됨.. • 결론. 각 환경 브랜치에 merge될때에만 docker 관련 build 테스트를 실행하기로 함
develop commands: - sh docker/run_git_diff.sh: timeout: 1500 betax: branch: betax commands: - sh docker/run_git_diff.sh: timeout: 1500 staging: branch: staging commands: - sh docker/run_git_diff.sh: timeout: 1500 production: branch: production commands: - sh docker/run_git_diff.sh: timeout: 1500 고로 docker관련 설정은 circleCI의deployment 레이어 에서만 실행 어떤 브랜치라도 실행하는 파일은 같음 run_git_diff.sh파일안에서 갱신된 파일을 보고 docker build할 리스트를 취득함
diff-tree -r --name-only --no-commit-id ORIG_HEAD)“ branch_name="${CIRCLE_BRANCH}" updated_nginx_status=false updated_unicorn_status=false updated_td-agent_status=false updated_rails_status=false for var in $changed_files do if [[ $var =~ ^docker/nginx/$branch_name ]]; then updated_nginx_status =true elif [[ $var =~ ^docker/unicorn/$branch_name ]]; then updated_unicorn_status=true elif [[ $var =~ ^docker/td-agent/$branch_name ]]; then updated_td-agent_status =true else updated_rails_status=true fi done
[ $updated_nginx_status ]; then sh docker/nginx/$branch_name/build_docker.sh //docker build sh docker/nginx/$branch_name/run_docker.sh //docker run sh docker/nginx/$branch_name/test/run_test.sh //serverspec으로 실행된 컨테이너의 동작 테스트 sh docker/nginx/$branch_name/push_docker.sh //테스트중 에러가 없다면 aws ecr에 docker push else fi if [ $updated_unicorn_status ]; then sh docker/unicorn/$branch_name/build_docker.sh sh docker/unicorn/$branch_name/run_docker.sh sh docker/unicorn/$branch_name/test/run_test.sh sh docker/unicorn/$branch_name/push_docker.sh else fi autumation docker run,test,push도 동일한 방식
docker nginx unicorn development beta staging productoon shared memcached redis elasticsearch development Build_docker.sh td-agent production mysql base Dockerfile docker- compose.yml docker/nginx/beta/xx docker/elasticsearch/d evelopment/xxx docker/td- agent/production/xxx 위와 같은 파일이 development branch에 merge됬다면
docker nginx unicorn development beta staging productoon shared memcached redis elasticsearch development Build_docker.sh td-agent production mysql base Dockerfile docker- compose.yml docker/nginx/beta/xx docker/elasticsearch/ development/xxx docker/td- agent/production/xxx 위와 같은 파일이 development branch에 merge됬다면 Development 디렉토리가 수정된 elasticsearch/development/build_ docker.sh파일이 실행됨
docker nginx production build_docker.sh unicorn development beta staging productoon build_docker.sh shared memcached redis elasticsearch development build_docker.sh td-agent production build_docker.sh mysql base Dockerfile docker- compose.yml docker/nginx/production /xx docker/elasticsearch/dev elopment/xxx docker/td- agent/production/xxx 위와 같은 파일이 production branch에 merge됬다면 docker/unicorn/producti on/xxx
docker nginx production build_docker.sh unicorn development beta staging productoon build_docker.sh shared memcached redis elasticsearch development build_docker.sh td-agent production build_docker.sh mysql base Dockerfile docker- compose.yml docker/nginx/production /xx docker/elasticsearch/dev elopment/xxx docker/td- agent/production/xxx 위와 같은 파일이 production branch에 merge됬다면 docker/unicorn/producti on/xxx Production 디렉토리가 수정된 nginx,unicorn,td-agent의 build_docker.sh파일이 전부 실행됨
이용해서 디플로이함 • Blue green deployment방식은 간지가 나지 않으므로 사용하지 않음 • AWS ECS의Minimum healthy percent,Maximum percent값을 잘 이용해주면 무정지 디플로이가 가능 • 클러스터내에 서버가20대가 있다고 가정 Minimum healthy percent:50, Maximum percent 100을 지정해주면 10대의 컨테이너가 죽고 새로운 컨테이너가 올라옴 -> 나머지 10대의 컨테이너가 죽고 새로운 컨테이너가 올라오게 됨
미들웨어별 환경별 환경변수 파일을 가짐 • 기본적으로 환경변수,ssh key등이 dockerfile안에서 필요할 경우 s3에서 취득함. 사용이 끝나면 반드시 삭제할 것 • 도커 컨테이너 실행시는 무조건 S3에서 최신 환경변수 파일을 취득 • S3에서 환경변수 관리시 version설정 필수
로 컨테너 기동 • 트러블 슈팅이 귀찮.. 컨테이너 안에 들어가서 레일즈 재기동한후의 동작상태가 알고싶을때가 많음 • 컨테이너 재기동하지 않고 컨테이너안에서 환경변수등을 적용시키고 싶음 • Rails 프로세스를 직접 컨테이너로 실행하는게 아닌 • Supervisord를 이용해서 rails프로세스를 기동 컨테이너는 supervisord가 기동하고 있으므로 컨테이너안에서 자유롭게 rails재기동이 가능 • 혹시 graceful하게 재기동하고 싶다면 unicornherder를 사용
Bundle install을 docker build와 따로 관리 Gemfile이 갱신되면 bundle install한 결과를 패키지화 해서 s3에 보관하는 batch가 따로 움직임 Dockerfile안에서는 해당 s3파일을 취득 타이밍에 따라선 bundle install한 패키지 내용이 최신이 아닐 가능성이 있으므로 bundle install은 build시 항시 실행(기존 패키지 거의 존재하므로 시간 많이 안걸림) bundle install
설정할까 고민 • 처음엔 lua script를 이용했는데 실제로 환경변수가 제대로 반영되있는지 트러블 슈팅이 힘들었음 • 구글링한 결과 외국성님들이 envsubst 로 nginx설정 하는걸 발견 • 결론. Envsubst를이용해서 컨테이너 기동시 nginx.conf파일을 생성
production} files set_env.sh dynamic_generate _nginx.conf.sh nginx.conf.templa te run_sh.sh 그외 도커 컨테이너에서 필요한 파일 Dockerfile build_docker.sh run_docker.sh deploy File name description dynamic_generate_nginx.conf.sh Envsubst커맨드 실행내용을 정의 nginx.conf.template nginx.conf를 만들기 위한 템플릿 파일
logdriver를 이용해서 표준 출력으로 받은 로그를 전부 전송 그외 로그들은 호스트인스턴스에 볼륨시켜둠 리얼타임 분석 목적이라면 Aws kinesis agent를 이용해서 AWS Kinesis Firehose에 전송 Firehose는 날짜별로 s3에 보존 AWS Athena로 분석
만듬 • 외부 소스의 변화에 의해 장애가 일어날 가능성이 있음 • 공개 리포지토리에 어떤 문제가 생겨도 시스템에 영향이 없게끔 하고 싶음 • 결론:도커 빌드시 테스트를 꼭 해야함, 사내용 베이스 이미지를 따로 가지고 있는게 안전 • 테스트는 뭘로? -> 인프라 쪽 테스틑 serverspec이 제일 유명
files set_env.sh set._key.sh run_sh.sh 그외 도커 컨테이너에서 필요한 파일 test Dockerfile build_docker.s h run_docker.sh push_docker.s h deploy test디렉토리 안에서 serverspec의 설정파일을 정의해둡니다. Circleci에서 해당 레이어의 파일이 갱신되었을때 build,run후 지정된 테스트 파일을 실행하게 됩니다.
빠르게 환경구축 가능 • 볼륨 기능 사용시 Docker for mac느림-> 해결책 docker-async사용 • 개발자 입장에서는 생각보다 학습 코스트가 높은듯?? • 좀처럼..적응하지 못함 • 개발과 운영 모두에게 혜택을 줄 잠재력을 가졌지만, 여전히 개발을 할 줄 아는 운영자여야 도커에 관심을 갖는다. 데브옵스를 할 수 없는 운영자에게 현업시스템에서 도커를 쓰게 한다면, 그 회사의 IT환경은 도커의 장점을 전혀 누릴 수 없음
production환경의 의존성을 없앤건 큰 성과 였지만 규모가 작아서 그런지 아직까지 큰 메리트가 없는 상태 • 현재 개발환경은 docker파, 안docker파로 나눠짐.. 프론트 엔지니어에게 특히 인기가 많았음. API쪽만 개발하는 분들에게는 인기가 없음..elasticsearch연계해서 개발할때만 사용하는 분위기 • 규모가 클수록 docker를 쓰면 좋다고 생각 • 규모가 작아도 해도 나쁠건 없지만 장점이 많이 사라지는 느낌이 듬