say hi to docker for ror
Serhii Koba, MobiDev
What's inside
Enjoy developing
headaches
- Different environments
- Manual launching
- Portability
- Scaling
- Long deploy
- Cleanup after trying new stuff
- Security
docker vs Vms
installation
https://docs.docker.com/engine/installation/
Dockerfile
- FROM (image)
- RUN
- ENV
- WORKDIR
- COPY
- EXPOSE
- ADD
- CMD
- VOLUME
FROM ruby:2.3.1
RUN apt-get update -qq && apt-get install \
-y build-essential libpq-dev \
imagemagick libmagickwand-dev libcurl3 \
libcurl3-gnutls libcurl4-openssl-dev nodejs
ENV RAILS_ROOT /var/www/app
RUN mkdir -p $RAILS_ROOT/tmp/pids
WORKDIR $RAILS_ROOT
COPY . .
VOLUME .:/var/www/app
EXPOSE 3000
CMD bundle exec rails s -p 3000 -b '0.0.0.0'
# стоит избегать длинных списков команд вроде таких:
RUN apt-get update
RUN apt-get upgrade
RUN apt-get install nginx
# А вместо этого писать все одной строкой:
RUN apt-get update &&\
apt-get upgrade &&\
apt-get install nginx
Шпаргалка по командам Dockerfile
FROM <имя-образа> — какой образ использовать в качестве базы (должна быть первой строкой в любом Dockerfile).
MAINTAINER <имя> — имя мейнтейнера данного Dockerfile.
RUN <команда> — запустить указанную команду внутри контейнера.
CMD <команда> — выполнить команду при запуске контейнера (обычно идет последней).
EXPOSE <порт> — список портов, которые будет слушать контейнер (используется механизмом линковки).
ENV <ключ> <значение> — создать переменную окружения.
ADD <путь> <путь> — скопировать файл/каталог внутрь контейнера/образа (первый аргумент может быть URL).
ENTRYPOINT <команда> — команда для запуска приложения в контейнере (по умолчанию /bin/sh -c).
VOLUME <путь> — пробросить в контейнер указанный каталог (аналог опции -v).
USER <имя> — сменить юзера внутри контейнера.
WORKDIR <путь> — сменить каталог внутри контейнера.
ONBUILD [ИНСТРУКЦИЯ] — запустить указанную инструкцию Dockerfile только в том случае, если образ используется для сборки другого образа (с помощью FROM).
docker hub
docker run -d --name firefox -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix kennethkl/firefox
Basic commands
- build
- run
- ps (-a)
- kill
- images
- exec
- rmi
- attach
(Ctrl+Q+P+Q)
> docker build -t "myapp:latest"
Building web
Step 1 : FROM growthhackers/ruby-node:2.3.1-6.3.1
---> dc04f4f6761b
Step 2 : RUN apt-get update -qq && apt-get install -y
---> libmagickwand-dev libqt4-dev libqtwebkit-dev php5-cli
---> Using cache
---> 9ab61f9186d4
Step 3 : ENV RAILS_ROOT /app
---> Using cache
---> f75c7870dad7
...
> docker run -p 3000 myapp:latest
> docker exec -i -t 4c01db0b339c bash
> docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d7886598dbe2 crosbymichael/redis:latest /redis-server --dir 33 minutes ago Up 33 minutes 6379/tcp redis,webapp/db
> docker kill 4c01db0b339c
> docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
postgres 9.3.5 746b819f315e 4 days ago 213.4 MB
> docker rmi 77af4d6b9913
MANUAL LAUNCHING SUCKS
say hi to docker compose
Docker Compose
- Works with a list of containers
- All configuration is in one place
- Builds, starts, stops containers
20 containers:
- 5 Rails applications
- 1 Database
- 4 Workes
- 4 Tests
- 1 SMTP server
- 1 AWS S3 server
- 4 Caches (gems, Redis)
= 23s
docker-compose.yml
- links
- ports
- image
- volumes
- environment
- etc
db:
image: postgres:latest
volumes:
- /var/lib/postgresql/data
environment:
POSTGRES_USER: "postgres"
POSTGRES_PASSWORD: "development"
web:
build: .
command: bundle exec rails s -p 3000 -b '0.0.0.0'
environment:
RAILS_ENV: development
links:
- db:postgresdb
ports:
- "3000:3000"
volumes:
- .:/var/www/app
database.yml
/etc/hosts
postgres: &default
adapter: postgresql
encoding: utf8
host: postgresdb
username: postgres
password: development
min_messages: warning
pool: 2
timeout: 5000
development:
<<: *default
database: myapp_development
Basic commands
- build
- up (-d)
- stop
- run
# Стартуем все контейнеры
docker-compose up -d
# Стартует только контейнер web
docker-compose run web
# Запускаем команду в контейнере
docker-compose run web rake db:migrate
# Остановить контейнеры
docker-compose stop
real life example
dockerized ror app in the wild
what's included
- Database (Postgres)
- Caching (Redis)
- Shared bundle cache
- Web app
- Worker (Sidekiq)
- Tests
Database
Postgres
db:
image: postgres:latest
volumes:
- /var/lib/postgresql/data
ports:
- '5432'
environment:
POSTGRES_USER: 'postgres'
POSTGRES_PASSWORD: 'development'
command: 'postgres -c fsync=off'
Redis
Stores cache and
user sessions
# Redis caching container
redis:
image: redis:2.8
ports:
# 6380 is for example
- "6380:6379"
Bundler Cache
Cache gems as volume
bundler-cache:
image: ruby:2.3.1
command: /bin/true
volumes:
- /usr/local/bundle
worker
Sidekiq
worker:
build: .
volumes_from:
- bundler-cache
- web
links:
- db:db
- redis
command: bundle exec sidekiq
Tests
Dockerfile.tests
- Install ruby and etc
- Install Chrome WebDriver
- Configure xvfb
- Use headless gem for tests...
tests:
build: .
dockerfile: Dockerfile.tests
command: bundle exec rspec
environment:
RAILS_ENV: test
links:
- db:db
volumes_from:
- bundler-cache
- web
WEB (RoR app)
Wrapping things up
web:
build: .
command: "bundle exec rails s -p 3000 -b '0.0.0.0'"
environment:
RAILS_ENV: development
links:
- db:postgresdb
- redis:redis
ports:
- "3000:3000"
volumes:
- .:/var/www/app
volumes_from:
- bundler-cache
common initialization
Basic steps
# Setup application
docker-compose build
docker-compose run web bundle install
docker-compose run web rake db:create db:migrate db:seed
# Run application
docker-compose up -d
# Setup tests
docker-compose run tests rake db:create db:migrate
# Run tests
docker-compose run tests
Docker for local dev
- fast and easy infrastructure from images
- auto launching
- portability
- close copy of production
- easy and secure to try new stuff
docker for productIon
- fast zero-downtime deploys
- ci
- scaling
- docker hub
- guaranteed to work the same as locally
- migrate to new software versions easily
next topics
- Docker networking
- Docker Machine
- Docker Swarm
- Docker UI, Shipyard
docker run -d -p 9000:9000 --privileged -v /var/run/docker.sock:/var/run/docker.sock uifd/ui-for-docker
credentials
http://meetup.mobidev.com.ua/
https://www.linkedin.com/in/serhii-koba
https://slides.com/skoba/docker-for-ror