데이터 과학

도커(Docker) - Dockerfile

학습 목표

  • Dockerfile 스크립트로 개발환경 구축을 자동화한다.
  • 정적 웹서비스 xwMOOC 개발 툴체인을 Dockerfile로 시연한다.

1. Docker Compose 설치

docker-compose를 설치하기 위해서는 docker가 설치되어 있어야 하고, curl이 필요하다.

root@docker:~# curl -L https://github.com/docker/compose/releases/download/1.3.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
root@docker:~# chmod +x /usr/local/bin/docker-compose

만약 “Permission denied” 오류가 나오면 sudo -i를 실행하고 다시 docker-compose 설치 명령을 실행한다.

root@docker:~# docker-compose --version
docker-compose version: 1.3.0
CPython version: 2.7.9
OpenSSL version: OpenSSL 1.0.1e 11 Feb 2013

2. xwMOOC 개발 툴체인 설치

도커 허브(Docker Hub) 저장소에서 LAMP, Pandoc, Jekyll, Ruby, RStudio, Shiny 서버를 검색해서 설치한다. 이외에도 자바스크립트를 포함하여 여러 도구가 정적 웹서비스 제공에 필요하다.

2.1. 한글 우분투 Dockerfile 생성

도커 자동화를 위해서 Dockerfile 스크립트를 작성한다. 먼저 statkclee/hangul 한글 우분투 이미지를 생성한다. docker build가 생성 명령어가 되고 -t가 이미지명을 부여하게 되고 .은 디폴트 초기설정으로 Dockerfile 스크립트를 지정한다.

root@dev:~/hangul# docker build -t statkclee/hangul .
# xwMOOC 
FROM ubuntu:14.04

# Hangul Install
RUN apt-get update && apt-get install -y \
    language-pack-ko && \
    dpkg-reconfigure locales && \
    locale-gen ko_KR.UTF-8 && \
    /usr/sbin/update-locale LANG=ko_KR.UTF-8

ENV LANG=ko_KR.UTF-8
ENV LANGUAGE=ko_KR.UTF-8
ENV LC_ALL=ko_KR.UTF-8

docker run -it 명령어로 /bin/bash를 실행해서 내부 한글이 되는 컨테이너 내부로 들어가면 한글이 정상적으로 CLI 모드에서 작동되는 것을 확인한다.

root@dev:~/hangul# docker run -it statkclee/hangul /bin/bash
root@2213b3f04bac:/# ls
bin   dev  home  lib64  mnt  proc  run   srv  tmp  var
boot  etc  lib   media  opt  root  sbin  sys  usr  한글.txt
root@2213b3f04bac:/# cat 한글.txt
한글 사랑...
abc...
123

2.2. Pandoc Dockerfile 설치

DockerfilePandoc을 설치한다. 하스칼 플랫폼을 이용한 방법도 있지만, cabal로 설치한다. pandoc을 환경변수 경로명에 추가한다.

# xwMOOC 작업환경 설정 Dockerfile
FROM ubuntu:14.04

# Pandoc 설치
RUN apt-get update && apt-get install -y \
    zlib1g-dev \
    cabal-install
RUN cabal update && cabal install \
    alex \
    happy \
    pandoc \
    pandoc-citeproc
    
ENV PATH /root/.cabal/bin:$PATH
root@dev:~/hangul# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
statkclee/pandoc    latest              c731a1b37d60        51 seconds ago      1.342 GB
statkclee/hangul    latest              b00700f6fe97        About an hour ago   215.3 MB
ubuntu              14.04               6d4946999d4f        8 days ago          188.3 MB
root@dev:~/hangul# docker run -it statkclee/pandoc /bin/bash
root@418652c231eb:/# pandoc -v
pandoc 1.14.0.4
Compiled with texmath 0.8.2, highlighting-kate 0.6.
Syntax highlighting is supported for the following languages:
    abc, actionscript, ada, agda, apache, asn1, asp, awk, bash, bibtex, boo, c,
    ...
    yacc, yaml, zsh
Default user data directory: /root/.pandoc
Copyright (C) 2006-2015 John MacFarlane
Web:  http://johnmacfarlane.net/pandoc
This is free software; see the source for copying conditions.
There is no warranty, not even for merchantability or fitness for a particular purpose.

2.3. 루비(Ruby)와 제킬(Jekyll) Dockerfile 설치

DockerfileRubyjekyllDockerfile 스크립트로 설치한다.

# Ruby 설치 from https://registry.hub.docker.com/_/ruby/
# 2.2.2-slim, 2.2-slim, 2-slim, slim (2.2/slim/Dockerfile)

FROM ubuntu:14.04

ENV RUBY_MAJOR 2.2
ENV RUBY_VERSION 2.2.2

# some of ruby's build scripts are written in ruby
# we purge this later to make sure our final image uses what we just built
RUN buildDeps=' \
        autoconf \
        bison \
        gcc \
        libbz2-dev \
        libgdbm-dev \
        libglib2.0-dev \
        libncurses-dev \
        libreadline-dev \
        libxml2-dev \
        libxslt-dev \
        make \
        ruby \
    ' \
    && set -x \
    && apt-get update \
    && apt-get install -y --no-install-recommends $buildDeps \
    && rm -rf /var/lib/apt/lists/* \
    && mkdir -p /usr/src/ruby \
    && curl -SL "http://cache.ruby-lang.org/pub/ruby/$RUBY_MAJOR/ruby-$RUBY_VERSION.tar.bz2" \
        | tar -xjC /usr/src/ruby --strip-components=1 \
    && cd /usr/src/ruby \
    && autoconf \
    && ./configure --disable-install-doc \
    && make -j"$(nproc)" \
    && make install \
    && rm -r /usr/src/ruby \
    && apt-get purge -y --auto-remove $buildDeps

# skip installing gem documentation
RUN echo 'gem: --no-rdoc --no-ri' >> "$HOME/.gemrc"

# install things globally, for great justice
ENV GEM_HOME /usr/local/bundle
ENV PATH $GEM_HOME/bin:$PATH

ENV BUNDLER_VERSION 1.10.4

RUN gem install bundler --version "$BUNDLER_VERSION" \
    && bundle config --global path "$GEM_HOME" \
    && bundle config --global bin "$GEM_HOME/bin"

# don't create ".bundle" in all our apps
ENV BUNDLE_APP_CONFIG $GEM_HOME

CMD [ "irb" ]

# Jekyll 설치 - 자바스크립트 실행환경(JavaScript Runtime) 필요

RUN apt-get update -qq && \
    apt-get install -y nodejs npm && \
    npm install -g coffee-script && \
    ln -s /usr/bin/nodejs /usr/bin/node

RUN gem install --no-rdoc --no-ri jekyll kramdown

RUN apt-get install -y python-pip
RUN pip install pandocfilters
root@dev:~/hangul# docker images
REPOSITORY             TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
statkclee/rubyjekyll   latest              6f4fac65d8c8        7 seconds ago       525.2 MB
statkclee/ruby         latest              943896407bed        42 minutes ago      376.8 MB
statkclee/pandoc       latest              c731a1b37d60        11 hours ago        1.342 GB
statkclee/hangul       latest              b00700f6fe97        13 hours ago        215.3 MB
ubuntu                 14.04               6d4946999d4f        8 days ago          188.3 MB
root@dev:~/hangul# docker run -it statkclee/rubyjekyll /bin/bash
root@ae5c1183c93b:/# ruby -v
ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux]
root@ae5c1183c93b:/# jekyll -v
jekyll 2.5.3

2.4. LAMP Dockerfile 설치

웹서비스 제공을 위해서 LAMP를 설치한다. 환경설정 스크립트는 GitHub 저장소 https://github.com/tutumcloud/lamp에서 가져온다. 또한 환경설정 파일은 Dockerfile이 위치한 곳에 함께 두고 설치한다.

######################################################
# 4. LAMP 설치 from https://registry.hub.docker.com/u/tutum/lamp/
# Git Repo. https://github.com/tutumcloud/lamp
# 환경설정 파일을 Dockerfile이 위치한 곳에 함께 두고 설치함.
######################################################

## Install packages
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update && \
  apt-get -y install supervisor git apache2 libapache2-mod-php5 mysql-server php5-mysql pwgen php-apc php5-mcrypt && \
  echo "ServerName localhost" >> /etc/apache2/apache2.conf

## Add image configuration and scripts
ADD start-apache2.sh /start-apache2.sh
ADD start-mysqld.sh /start-mysqld.sh
ADD run.sh /run.sh
RUN chmod 755 /*.sh
ADD my.cnf /etc/mysql/conf.d/my.cnf
ADD supervisord-apache2.conf /etc/supervisor/conf.d/supervisord-apache2.conf
ADD supervisord-mysqld.conf /etc/supervisor/conf.d/supervisord-mysqld.conf

## Remove pre-installed database
RUN rm -rf /var/lib/mysql/*

## Add MySQL utils
ADD create_mysql_admin_user.sh /create_mysql_admin_user.sh
RUN chmod 755 /*.sh

## config to enable .htaccess
ADD apache_default /etc/apache2/sites-available/000-default.conf
RUN a2enmod rewrite

## Configure /app folder with sample app
RUN git clone https://github.com/fermayo/hello-world-lamp.git /app
RUN mkdir -p /app && rm -fr /var/www/html && ln -s /app /var/www/html

##Enviornment variables to configure php
ENV PHP_UPLOAD_MAX_FILESIZE 10M
ENV PHP_POST_MAX_SIZE 10M

## Add volumes for MySQL 
VOLUME  ["/etc/mysql", "/var/lib/mysql" ]

EXPOSE 80 3306
CMD ["/run.sh"]

2.5. xwMOOC Dockerfile 설치 파일

xwMOOC 개발 환경을 Dockerfile 스크립트를 설치한다. xwMOOC 기존 가상컴퓨터 구축에 사용한 파일도 있지만, 이를 재사용하고, 도커허브 공식 이미지에 있는 Dockerfile을 받아 ubuntu:14.04에서 출발해서 쌓아올린다.

xwMOOC Dockerfile 구성

# xwMOOC 작업환경 설정 Dockerfile
FROM ubuntu:14.04

######################################################
# 0.한글(Hangul) 설치
######################################################

RUN apt-get update && apt-get install -y \
    language-pack-ko && \
    dpkg-reconfigure locales && \
    locale-gen ko_KR.UTF-8 && \
    /usr/sbin/update-locale LANG=ko_KR.UTF-8

ENV LANG=ko_KR.UTF-8
ENV LANGUAGE=ko_KR.UTF-8
ENV LC_ALL=ko_KR.UTF-8

######################################################
# 1. Pandoc 설치
######################################################

RUN apt-get update && apt-get install -y \
    zlib1g-dev \
    cabal-install
RUN cabal update && cabal install \
    alex \
    happy \
    pandoc \
    pandoc-citeproc

ENV PATH /root/.cabal/bin:$PATH

######################################################
# 2. Ruby 설치 from https://registry.hub.docker.com/_/ruby/
## 2.2.2-slim, 2.2-slim, 2-slim, slim (2.2/slim/Dockerfile)
######################################################

RUN apt-get update \
    && apt-get install -y --no-install-recommends \
        bzip2 \
        ca-certificates \
        curl \
        libffi-dev \
        libgdbm3 \
        libssl-dev \
        libyaml-dev \
        procps \
        zlib1g-dev \
    && rm -rf /var/lib/apt/lists/*

ENV RUBY_MAJOR 2.2
ENV RUBY_VERSION 2.2.2

# some of ruby's build scripts are written in ruby
# we purge this later to make sure our final image uses what we just built
RUN buildDeps=' \
        autoconf \
        bison \
        gcc \
        libbz2-dev \
        libgdbm-dev \
        libglib2.0-dev \
        libncurses-dev \
        libreadline-dev \
        libxml2-dev \
        libxslt-dev \
        make \
        ruby \
    ' \
    && set -x \
    && apt-get update \
    && apt-get install -y --no-install-recommends $buildDeps \
    && rm -rf /var/lib/apt/lists/* \
    && mkdir -p /usr/src/ruby \
    && curl -SL "http://cache.ruby-lang.org/pub/ruby/$RUBY_MAJOR/ruby-$RUBY_VERSION.tar.bz2" \
        | tar -xjC /usr/src/ruby --strip-components=1 \
    && cd /usr/src/ruby \
    && autoconf \
    && ./configure --disable-install-doc \
    && make -j"$(nproc)" \
    && make install \
    && rm -r /usr/src/ruby \
    && apt-get purge -y --auto-remove $buildDeps

# skip installing gem documentation
RUN echo 'gem: --no-rdoc --no-ri' >> "$HOME/.gemrc"

# install things globally, for great justice
ENV GEM_HOME /usr/local/bundle
ENV PATH $GEM_HOME/bin:$PATH

ENV BUNDLER_VERSION 1.10.4

RUN gem install bundler --version "$BUNDLER_VERSION" \
    && bundle config --global path "$GEM_HOME" \
    && bundle config --global bin "$GEM_HOME/bin"

# don't create ".bundle" in all our apps
ENV BUNDLE_APP_CONFIG $GEM_HOME

CMD [ "irb" ]

######################################################
# 3. Jekyll 설치 - 자바스크립트 실행환경(JavaScript Runtime) 필요
######################################################

RUN apt-get update -qq && \
    apt-get install -y nodejs npm && \
    npm install -g coffee-script && \
    ln -s /usr/bin/nodejs /usr/bin/node

RUN gem install --no-rdoc --no-ri jekyll kramdown

RUN apt-get install -y python-pip
RUN pip install pandocfilters

######################################################
# 4. LAMP 설치 from https://registry.hub.docker.com/u/tutum/lamp/
# Git Repo. https://github.com/tutumcloud/lamp
# 환경설정 파일을 Dockerfile이 위치한 곳에 함께 두고 설치함.
######################################################

## Install packages
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update && \
  apt-get -y install supervisor git apache2 libapache2-mod-php5 mysql-server php5-mysql pwgen php-apc php5-mcrypt && \
  echo "ServerName localhost" >> /etc/apache2/apache2.conf

## Add image configuration and scripts
ADD start-apache2.sh /start-apache2.sh
ADD start-mysqld.sh /start-mysqld.sh
ADD run.sh /run.sh
RUN chmod 755 /*.sh
ADD my.cnf /etc/mysql/conf.d/my.cnf
ADD supervisord-apache2.conf /etc/supervisor/conf.d/supervisord-apache2.conf
ADD supervisord-mysqld.conf /etc/supervisor/conf.d/supervisord-mysqld.conf

## Remove pre-installed database
RUN rm -rf /var/lib/mysql/*

## Add MySQL utils
ADD create_mysql_admin_user.sh /create_mysql_admin_user.sh
RUN chmod 755 /*.sh

## config to enable .htaccess
ADD apache_default /etc/apache2/sites-available/000-default.conf
RUN a2enmod rewrite

## Configure /app folder with sample app
RUN git clone https://github.com/fermayo/hello-world-lamp.git /app
RUN mkdir -p /app && rm -fr /var/www/html && ln -s /app /var/www/html

##Enviornment variables to configure php
ENV PHP_UPLOAD_MAX_FILESIZE 10M
ENV PHP_POST_MAX_SIZE 10M

## Add volumes for MySQL 
VOLUME  ["/etc/mysql", "/var/lib/mysql" ]

EXPOSE 80 3306
CMD ["/run.sh"]


######################################################
# 5. 공통 개발 도구 
######################################################

RUN apt-get install -y \
    git \
    libxml2-dev \
    python \
    build-essential \
    make \
    gcc \
    python-dev \
    locales \
    python-pip

3. 도커허브 푸쉬(Push)

작업한 이미지를 도커허브에 마치 GitHub에 작업 산출물을 저장하듯이 클라우드에 저장한다. 이를 위해서 먼저 도커 이미지의 사용자명/이미지명 형식에 맞춰 태그를 줘야 한다. 처음 도커허브에 푸쉬하는 경우 사용자명, 비밀번호, 전자우편주소를 확인한다.

root@dev:~/hangul# docker push statkclee/xwmooc
The push refers to a repository [statkclee/xwmooc] (len: 1)
c731xxxxxxx: Image push failed

Please login prior to push:
Username: statkclee
Password:
Email: gildong@gmail.com
WARNING: login credentials saved in /root/.docker/config.json
Login Succeeded
The push refers to a repository [statkclee/xwmooc] (len: 1)
c731a1b37d60: Image already exists
5f9029e97976: Image successfully pushed
de53599479e9: Image successfully pushed
b00700f6fe97: Pushing     32 B/32 B
b00700f6fe97: Image successfully pushed
c722f35f2615: Pushing     32 B/32 B
c722f35f2615: Image successfully pushed
8af0d14f5f9a: Image successfully pushed
5cb1a6663b55: Image successfully pushed
6d4946999d4f: Image already exists
9fd3c8c9af32: Image successfully pushed
435050075b3f: Image successfully pushed
428b411c28f0: Buffering to Disk
428b411c28f0: Image successfully pushed
Digest: sha256:c36cfc4b0c9467c3be9af5f9ff4e095960033cd7301d9c5a08e512f8c92d62fb

태그가 없는 이미지 삭제

root@dev:~# docker rmi $(docker images | awk '/^<none>/ {print $3}')