ETL 메커니즘을 Docker로 구현해 보았습니다.
이전 세미나에서 데이터 분석 기반의 이야기를 들었을 때 규모가 너무 커서 잘 모르는 경우가 있었습니다.
CPU보다 GPU가 좋다든가, IoT의 데이터를 실시간으로 업로드한다든지 실제로 그런 일 좀 할 수 없고, 모르면 분위기 잡을 수 없는 사람이 대부분이라고 생각합니다.
그러나 좀 더 규모가 작은 데이터에서도 분석 사용하고 싶은, 분석하고 싶다는 사람도 많을까 생각합니다.
이번에 해본 것은 해석원의 데이터를 ETL 툴로 Google의 BigQuery에 데이터를 집약하는 구조를 Docker를 사용해 구현해 보았습니다.
운영 환경
호스트
품목
버전
os
OS X El Capitan 10.11.6
dokcer
17.09.0-ce
docker-compose
1.16.1
루비
2.3.5
docker가 작동하면 어떤 환경에서도 문제가 없습니다. 다만, dokcer와 docker-compose는 낡은 버젼이라고 동작하지 않을 가능성도 있으므로, 가능한 한 최신 버젼이 좋을까라고 생각합니다.
컨테이너
ETL + 작업 스케줄러 (ETL : Embulk, 작업 스케줄러 : kuroko2)
품목
버전
base image
alpine:3.6
openjdk
1.8.0_131
루비
2.3.5p376
jruby
jruby 9.1.14.0 (2.3.3)
bundler
1.16.0
rails
5.1.4
puma
5.1.4
kuroko2
0.4.3
Embulk
v0.8.38
ETL은 Embulk을 사용하고 있으며 작업 스케줄러는 쿡 패드의 쿠로코 2을 사용합니다.
데이터베이스
품목
버전
base image
mariadb:latest
mariadb
15.1 Distrib 10.2.11
실시간 모니터링(netdata)
품목
버전
base image
titpetric/netdata:latest
netdata
1.8.0-624-gf14f228_rolling
ETL+ 작업 스케줄러 컨테이너 작성
kuroko2의 초기 설정
쿡 패드의 쿠로코 2 을 사용하기 위해 Administrator Guide 을 참고로 초기 설정을 합니다.
Dockerfile내에서 rails new
그러면 이미지 사이즈가 비대화하므로, 이미지 밖에서 rails new
한 것을 docker의 이미지안에 짜넣습니다.
rails new my_kuroko2 --database=mysql --skip-turbolinks --skip-javascript -m https://raw.githubusercontent.com/cookpad/kuroko2/master/app_template.rb
Docker 이미지 만들기
본래는 1프로세스 1컨테이너가 이상입니다만, ETL툴의 Embulk는 커멘드 툴이며, 작업 스케줄러의 Kuroko2로 Rails Sever(puma)와 작업 실행하는 프로세스와 복수 가동시키지 않으면 안 되었기 때문에, 1컨테이너에 복수 기능을 갖게 하기로 했습니다.
DockerfileFROM ayaran/openjdk:8u131
MAINTAINER [email protected]
RUN echo "http://dl-cdn.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories
RUN echo "http://dl-cdn.alpinelinux.org/alpine/v3.5/main" >> /etc/apk/repositories
RUN echo "http://dl-cdn.alpinelinux.org/alpine/v3.5/community" >> /etc/apk/repositories
RUN apk update && apk add --no-cache \
openrc \
curl \
cmake \
mysql-dev \
mysql-client \
build-base \
libxml2-dev \
libxslt-dev \
linux-headers \
libffi-dev \
openssl \
nodejs \
jruby \
tzdata
RUN apk add --no-cache \
ruby=2.3.6-r0 \
ruby-dev=2.3.6-r0 \
ruby-bigdecimal=2.3.6-r0 \
ruby-rdoc=2.3.6-r0 \
ruby-io-console=2.3.6-r0 \
ruby-irb=2.3.6-r0
RUN gem install --no-doc bundler
RUN curl -L "https://dl.embulk.org/embulk-latest.jar" -o /usr/local/bin/embulk
RUN chmod +x /usr/local/bin/embulk
COPY ./Gemfile /opt/embulk/Gemfile
RUN gem install --no-doc bundler --install-dir /opt/embluk/bundle/ruby/2.3.0/gems
RUN embulk bundle install --gemfile /opt/embulk/Gemfile --path /opt/embulk/bundle
ADD ./my_kuroko2 /opt/kuroko2
WORKDIR /opt/kuroko2
RUN bundle install --gemfile /opt/kuroko2/Gemfile --path /opt/kuroko2/bundle
COPY ./config/database.yml /opt/kuroko2/config/database.yml
COPY ./config/application.rb /opt/kuroko2/config/application.rb
RUN mkdir -p /opt/kuroko2/tmp/pids
COPY ./scripts/db-migrate /etc/init.d/db-migrate
COPY ./scripts/puma /etc/init.d/puma
COPY ./scripts/command-executor /etc/init.d/command-executor
COPY ./scripts/job-scheduler /etc/init.d/job-scheduler
COPY ./scripts/workflow-processor /etc/init.d/workflow-processor
RUN rc-update add db-migrate default
RUN rc-update add puma default
RUN rc-update add command-executor default
RUN rc-update add job-scheduler default
RUN rc-update add workflow-processor default
RUN rc-status && touch /run/openrc/softlevel
RUN sed -i -- 's/^tty/#tty/g' /etc/inittab
각 프로세스를 데몬화하고 기동하고 싶었기 때문에 OpenRC의 기동 스크립트를 만들어 설치하고 있습니다.
특히, 어플리케이션 컨테이너를 기동할 때에 Database의 초기 기동이 완료하고 있는 것이 전제이므로, docker docs 를 참고로 Database의 최초 기동 완료를 확인하고 나서 db:migrate
가 움직이는 스크립트 작성하고 있습니다.
db-migrate#!/sbin/openrc-run
prog=db-migrate
RAILS_ROOT=/opt/kuroko2
host=database
user=kuroko
password=kuroko
cmd="/usr/bin/bundle exec rails db:migrate"
start() {
echo -n $"Starting $prog: "
until mysql -h"$host" -u"$user" -p"$password" -e "show databases;"; do
echo -n "MySQL is unavailable - sleeping"
sleep 1
done
>&2 echo "MySQL is up - executing command"
cd $RAILS_ROOT
$cmd
RETVAL=$?
echo
eend $?
}
만든 컨테이너들의 시작
docker-compose로 기동시키기 위해서, 아래 docker-compose.yml
를 준비.
docker-compose.ymlversion: '3.2'
services:
database:
hostname: mariadb
container_name: mariadb
image: mariadb
expose:
- 3306
environment:
- MYSQL_RANDOM_ROOT_PASSWORD=yes
- MYSQL_DATABASE=kuroko2_development
- MYSQL_USER=kuroko
- MYSQL_PASSWORD=kuroko
restart: always
kuroko2:
hostname: kuroko2
container_name: kuroko2
image: ayaran/kuroko2
expose:
- 80
ports:
- 80:80
links:
- database:database
depends_on:
- "database"
volumes:
- ./.env:/opt/kuroko2/.env
- /sys/fs/cgroup:/sys/fs/cgroup:ro
command: /sbin/init
restart: always
netdata:
hostname: netdata
container_name: netdata
image: titpetric/netdata
expose:
- 19999
ports:
- 19999:19999
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /var/run/docker.sock:/var/run/docker.sock
environment:
- "TZ=Japan"
tty: true
restart: always
Database를 영속화하는 경우는 호스트측의 volume를 마운트 해 두면 좋다.
database:
hostname: mariadb
container_name: mariadb
image: mariadb
expose:
- 3306
environment:
- MYSQL_RANDOM_ROOT_PASSWORD=yes
- MYSQL_DATABASE=kuroko2_development
- MYSQL_USER=kuroko
- MYSQL_PASSWORD=kuroko
volumes:
- /path/to/mysql:/var/lib/mysql
restart: always
부팅
docker-compose -f docker-compose.yml up -d
이제 시작합니다.
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
185609c9aba9 ayaran/kuroko2 "/sbin/init" 6 seconds ago Up 4 seconds 0.0.0.0:80->80/tcp kuroko2
5103d6d4b17f mariadb "docker-entrypoint..." 3 hours ago Up 26 minutes 3306/tcp mariadb
4fc893ed9d35 titpetric/netdata "/run.sh" 3 hours ago Up 26 minutes 0.0.0.0:19999->19999/tcp netdata
http://localhost/
에 액세스하면 GoogleAuth 화면이 나오고,
인증하면 kuroko2 화면이 나타납니다.
여기에서 BigQuery로 데이터 전송할 JOB를 등록하여 실행합니다.
또한 http://localhost:19999
에 액세스하면 리소스 모니터링 화면도 볼 수 있습니다.
요약
실제로 데이터를 전송하는 곳까지 걸리지 않았지만, 생각했던 것보다 쉽게 구조를 만들 수있었습니다.
(컨테이너의 이미지만 있으면 약간의 config만 준비하면 명령 하나 두드리는 것만으로 움직이는 것이므로.)
Reference
이 문제에 관하여(ETL 메커니즘을 Docker로 구현해 보았습니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/ayalan/items/7ec3632d75c727575a4b
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
kuroko2의 초기 설정
쿡 패드의 쿠로코 2 을 사용하기 위해 Administrator Guide 을 참고로 초기 설정을 합니다.
Dockerfile내에서
rails new
그러면 이미지 사이즈가 비대화하므로, 이미지 밖에서 rails new
한 것을 docker의 이미지안에 짜넣습니다.rails new my_kuroko2 --database=mysql --skip-turbolinks --skip-javascript -m https://raw.githubusercontent.com/cookpad/kuroko2/master/app_template.rb
Docker 이미지 만들기
본래는 1프로세스 1컨테이너가 이상입니다만, ETL툴의 Embulk는 커멘드 툴이며, 작업 스케줄러의 Kuroko2로 Rails Sever(puma)와 작업 실행하는 프로세스와 복수 가동시키지 않으면 안 되었기 때문에, 1컨테이너에 복수 기능을 갖게 하기로 했습니다.
Dockerfile
FROM ayaran/openjdk:8u131
MAINTAINER [email protected]
RUN echo "http://dl-cdn.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories
RUN echo "http://dl-cdn.alpinelinux.org/alpine/v3.5/main" >> /etc/apk/repositories
RUN echo "http://dl-cdn.alpinelinux.org/alpine/v3.5/community" >> /etc/apk/repositories
RUN apk update && apk add --no-cache \
openrc \
curl \
cmake \
mysql-dev \
mysql-client \
build-base \
libxml2-dev \
libxslt-dev \
linux-headers \
libffi-dev \
openssl \
nodejs \
jruby \
tzdata
RUN apk add --no-cache \
ruby=2.3.6-r0 \
ruby-dev=2.3.6-r0 \
ruby-bigdecimal=2.3.6-r0 \
ruby-rdoc=2.3.6-r0 \
ruby-io-console=2.3.6-r0 \
ruby-irb=2.3.6-r0
RUN gem install --no-doc bundler
RUN curl -L "https://dl.embulk.org/embulk-latest.jar" -o /usr/local/bin/embulk
RUN chmod +x /usr/local/bin/embulk
COPY ./Gemfile /opt/embulk/Gemfile
RUN gem install --no-doc bundler --install-dir /opt/embluk/bundle/ruby/2.3.0/gems
RUN embulk bundle install --gemfile /opt/embulk/Gemfile --path /opt/embulk/bundle
ADD ./my_kuroko2 /opt/kuroko2
WORKDIR /opt/kuroko2
RUN bundle install --gemfile /opt/kuroko2/Gemfile --path /opt/kuroko2/bundle
COPY ./config/database.yml /opt/kuroko2/config/database.yml
COPY ./config/application.rb /opt/kuroko2/config/application.rb
RUN mkdir -p /opt/kuroko2/tmp/pids
COPY ./scripts/db-migrate /etc/init.d/db-migrate
COPY ./scripts/puma /etc/init.d/puma
COPY ./scripts/command-executor /etc/init.d/command-executor
COPY ./scripts/job-scheduler /etc/init.d/job-scheduler
COPY ./scripts/workflow-processor /etc/init.d/workflow-processor
RUN rc-update add db-migrate default
RUN rc-update add puma default
RUN rc-update add command-executor default
RUN rc-update add job-scheduler default
RUN rc-update add workflow-processor default
RUN rc-status && touch /run/openrc/softlevel
RUN sed -i -- 's/^tty/#tty/g' /etc/inittab
각 프로세스를 데몬화하고 기동하고 싶었기 때문에 OpenRC의 기동 스크립트를 만들어 설치하고 있습니다.
특히, 어플리케이션 컨테이너를 기동할 때에 Database의 초기 기동이 완료하고 있는 것이 전제이므로, docker docs 를 참고로 Database의 최초 기동 완료를 확인하고 나서
db:migrate
가 움직이는 스크립트 작성하고 있습니다.db-migrate
#!/sbin/openrc-run
prog=db-migrate
RAILS_ROOT=/opt/kuroko2
host=database
user=kuroko
password=kuroko
cmd="/usr/bin/bundle exec rails db:migrate"
start() {
echo -n $"Starting $prog: "
until mysql -h"$host" -u"$user" -p"$password" -e "show databases;"; do
echo -n "MySQL is unavailable - sleeping"
sleep 1
done
>&2 echo "MySQL is up - executing command"
cd $RAILS_ROOT
$cmd
RETVAL=$?
echo
eend $?
}
만든 컨테이너들의 시작
docker-compose로 기동시키기 위해서, 아래 docker-compose.yml
를 준비.
docker-compose.ymlversion: '3.2'
services:
database:
hostname: mariadb
container_name: mariadb
image: mariadb
expose:
- 3306
environment:
- MYSQL_RANDOM_ROOT_PASSWORD=yes
- MYSQL_DATABASE=kuroko2_development
- MYSQL_USER=kuroko
- MYSQL_PASSWORD=kuroko
restart: always
kuroko2:
hostname: kuroko2
container_name: kuroko2
image: ayaran/kuroko2
expose:
- 80
ports:
- 80:80
links:
- database:database
depends_on:
- "database"
volumes:
- ./.env:/opt/kuroko2/.env
- /sys/fs/cgroup:/sys/fs/cgroup:ro
command: /sbin/init
restart: always
netdata:
hostname: netdata
container_name: netdata
image: titpetric/netdata
expose:
- 19999
ports:
- 19999:19999
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /var/run/docker.sock:/var/run/docker.sock
environment:
- "TZ=Japan"
tty: true
restart: always
Database를 영속화하는 경우는 호스트측의 volume를 마운트 해 두면 좋다.
database:
hostname: mariadb
container_name: mariadb
image: mariadb
expose:
- 3306
environment:
- MYSQL_RANDOM_ROOT_PASSWORD=yes
- MYSQL_DATABASE=kuroko2_development
- MYSQL_USER=kuroko
- MYSQL_PASSWORD=kuroko
volumes:
- /path/to/mysql:/var/lib/mysql
restart: always
부팅
docker-compose -f docker-compose.yml up -d
이제 시작합니다.
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
185609c9aba9 ayaran/kuroko2 "/sbin/init" 6 seconds ago Up 4 seconds 0.0.0.0:80->80/tcp kuroko2
5103d6d4b17f mariadb "docker-entrypoint..." 3 hours ago Up 26 minutes 3306/tcp mariadb
4fc893ed9d35 titpetric/netdata "/run.sh" 3 hours ago Up 26 minutes 0.0.0.0:19999->19999/tcp netdata
http://localhost/
에 액세스하면 GoogleAuth 화면이 나오고,
인증하면 kuroko2 화면이 나타납니다.
여기에서 BigQuery로 데이터 전송할 JOB를 등록하여 실행합니다.
또한 http://localhost:19999
에 액세스하면 리소스 모니터링 화면도 볼 수 있습니다.
요약
실제로 데이터를 전송하는 곳까지 걸리지 않았지만, 생각했던 것보다 쉽게 구조를 만들 수있었습니다.
(컨테이너의 이미지만 있으면 약간의 config만 준비하면 명령 하나 두드리는 것만으로 움직이는 것이므로.)
Reference
이 문제에 관하여(ETL 메커니즘을 Docker로 구현해 보았습니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/ayalan/items/7ec3632d75c727575a4b
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
version: '3.2'
services:
database:
hostname: mariadb
container_name: mariadb
image: mariadb
expose:
- 3306
environment:
- MYSQL_RANDOM_ROOT_PASSWORD=yes
- MYSQL_DATABASE=kuroko2_development
- MYSQL_USER=kuroko
- MYSQL_PASSWORD=kuroko
restart: always
kuroko2:
hostname: kuroko2
container_name: kuroko2
image: ayaran/kuroko2
expose:
- 80
ports:
- 80:80
links:
- database:database
depends_on:
- "database"
volumes:
- ./.env:/opt/kuroko2/.env
- /sys/fs/cgroup:/sys/fs/cgroup:ro
command: /sbin/init
restart: always
netdata:
hostname: netdata
container_name: netdata
image: titpetric/netdata
expose:
- 19999
ports:
- 19999:19999
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /var/run/docker.sock:/var/run/docker.sock
environment:
- "TZ=Japan"
tty: true
restart: always
database:
hostname: mariadb
container_name: mariadb
image: mariadb
expose:
- 3306
environment:
- MYSQL_RANDOM_ROOT_PASSWORD=yes
- MYSQL_DATABASE=kuroko2_development
- MYSQL_USER=kuroko
- MYSQL_PASSWORD=kuroko
volumes:
- /path/to/mysql:/var/lib/mysql
restart: always
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
185609c9aba9 ayaran/kuroko2 "/sbin/init" 6 seconds ago Up 4 seconds 0.0.0.0:80->80/tcp kuroko2
5103d6d4b17f mariadb "docker-entrypoint..." 3 hours ago Up 26 minutes 3306/tcp mariadb
4fc893ed9d35 titpetric/netdata "/run.sh" 3 hours ago Up 26 minutes 0.0.0.0:19999->19999/tcp netdata
실제로 데이터를 전송하는 곳까지 걸리지 않았지만, 생각했던 것보다 쉽게 구조를 만들 수있었습니다.
(컨테이너의 이미지만 있으면 약간의 config만 준비하면 명령 하나 두드리는 것만으로 움직이는 것이므로.)
Reference
이 문제에 관하여(ETL 메커니즘을 Docker로 구현해 보았습니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/ayalan/items/7ec3632d75c727575a4b텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)