Bartosz Tkaczewski - Przygód z Dockerem ciąg dalszy
http://www.tsh.io
Docker jest zauważalny już niemal wszędzie. Na prezentacji zobaczysz działające środowisko developerskie, poznasz kilka sztuczek, jak sobie z nim dobrze radzić i efektywnie pracować, zobaczysz też, jak szybko można prosty projekt wzbogacić o zaawansowane stacki aplikacji (na przykładzie ELK). Postaram się również opowiedzieć, jak można sobie z tym potworkiem poradzić na produkcji.
Prezentacja z Uszanowanka Programowanka #16 - http://www.meetup.com/Uszanowanko-Programowanko/events/234826115/
1. Przygód z Dockerem ciąg
dalszy
Słów kilka o Dockerze
Bartosz Tkaczewski
email: tkaczu@tsh.io twitter: @btkaczewski github: tkaczu1
2. Plan prezentacji
Docker - co to jest, jak działa, zalety i jak
zainstalować?
Środowisko developerskie
Jak używacie
Przydatne polecenia
Co na produkcji
2
3. - co to jest?
Docker to narzędzie, które pozwala umieścić
aplik ację oraz jej zależności w lekkim ,
przenośnym, wirtualnym kontenerze - który
można uruchomić na prawie każdym serwerze .
To gwarantuje, że oprogramowanie będzie zawsze
działać tak samo, niezależnie od architektury,
systemu i środowiska w którym go uruchomi.
3
4. - Docker VS VM
Maszyny wirtualne
np. Vagrant
Kontenery Docker
5. - jakie zalety?
Wyeliminujesz SOA#1!
Izolacja aplikacji
Szybkie wdrażanie aplikacji
Łatwość konfiguracji
Wieloplatformowość
Możliwość ponownego użycia
Wygodna obsługa zależności
Społeczność
6. - jak zainstalować?
Linux:
Ubuntu: https://docs.docker.com/engine/installation/linux/ubuntulinux/
Arch Linux: https://docs.docker.com/engine/installation/linux/archlinux/
Debian: https://docs.docker.com/engine/installation/linux/debian/
Fedora: https://docs.docker.com/engine/installation/linux/fedora/
Mac OS X, macOS
Toolbox (zalecana) - https://docs.docker.com/toolbox/toolbox_install_mac/
Natywny - https://docs.docker.com/docker-for-mac/
Windows
Toolbox (zalecana) - https://docs.docker.com/toolbox/toolbox_install_windows/
Natywny - https://docs.docker.com/docker-for-windows/
8. - środowisko developerskie
Tworzenie maszyny developerskiej - docker-machine create
# tkaczu @ TkaczBook in ~/Workspace/TSH/Uszanowanko/Docker on git:master o [17:21:54]
$ docker-machine create --driver=virtualbox --virtualbox-disk-size=10240 --virtualbox-memory=3072 --virtualbox-cpu-count=2
development-machine
Running pre-create checks ...
(development-machine) Latest release for github.com/boot2docker/boot2docker is v1.12.2
(development-machine) Downloading /Users/tkaczu/.docker/machine/cache/boot2docker.iso from https: //github.com/boot2docker/
boot2docker/releases/download/v1.12.2/boot2docker.iso ...
Creating machine ...
(development-machine) Copying /Users/tkaczu/.docker/machine/cache/boot2docker.iso to /Users/tkaczu/.docker/machine/machines/
development-machine/boot2docker.iso ...
(development-machine) Creating VirtualBox VM ...
(development-machine) Creating SSH key ...
(development-machine) Starting the VM ...
(development-machine) Check network to re-create if needed ...
(development-machine) Waiting for an IP ...
Waiting for machine to be running, this may take a few minutes ...
Detecting operating system of created instance ...
Waiting for SSH to be available ...
Detecting the provisioner ...
Provisioning with boot2docker ...
Copying certs to the local machine directory ...
Copying certs to the remote machine ...
Setting Docker configuration on the remote daemon ...
Checking connection to Docker ...
Docker is up and running!
To see how to connect your Docker Client to the Docker Engine running on this virtual machine, run: docker-machine env
development-machine
9. - środowisko developerskie
Pobranie ustawień maszyny - docker-machine env
# tkaczu @ TkaczBook in ~/Workspace/TSH/Uszanowanko/Docker on git:master o [17:24:39]
$ docker-machine env development-machine
export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp: //192.168.99.101:2376"
export DOCKER_CERT_PATH="/Users/tkaczu/.docker/machine/machines/development-machine"
export DOCKER_MACHINE_NAME="development-machine"
# Run this command to configure your shell:
# eval $(docker-machine env development-machine)
Ustawienie zmiennych środowiskowych maszyny
#tkaczu @ TkaczBook in ~/Workspace/TSH/Uszanowanko/Docker on git:master o [17:42:30]
$ eval $(docker-machine env development-machine)
10. - środowisko developerskie
Współdzielenie plików na maszynie developerskiej przez NFS
# tkaczu @ TkaczBook in ~/Workspace/TSH/Uszanowanko/Docker on git:master o [18:02:51]
$ docker-machine-nfs development-machine --shared-folder=/Users/tkaczu/Workspace/TSH/Uszanowanko/Docker --nfs-
config="-mapall=tkaczu:staff 192.168.99.100" --mount-
opts="rw,async,noatime,rsize=32768,wsize=32768,proto=tcp,nfsvers=3" -f
[INFO] Configuration:
- Machine Name: development-machine
- Shared Folder: /Users/tkaczu/Workspace/TSH/Uszanowanko/Docker
- Mount Options: rw,async,noatime,rsize=32768,wsize=32768,proto=tcp,nfsvers=3
- Force: true
[INFO] machine presence ... OK
[INFO] machine running ... OK
[INFO] Lookup mandatory properties ... OK
- Machine IP: 192.168.99.101
- Network ID: vboxnet0
- NFSHost IP: 192.168.99.1
[INFO] Configure NFS ...
!!! Sudo will be necessary for editing /etc/exports !!!
[INFO] Configure Docker Machine ... OK
[INFO] Restart Docker Machine ... OK
[INFO] Verify NFS mount ... OK
--- --- --- --- --- --- --- --- --- --- --- --- --- --- --
The docker-machine 'development-machine'
is now mounted with NFS!
ENJOY high speed mounts :D
--- --- --- --- --- --- --- --- --- --- --- --- --- --- --
11. - poznajmy się!
Dockerfile - opis bazowego konteneru aplikacji
FROM ruby:2.3.1 # Bazowy obraz - zawiera ruby i wszystkie paczki
MAINTAINER "Bartosz 'tkaczu' Tkaczewski"
RUN apt-get update -qq && apt-get upgrade -qq # aktualizujemy nasz image
RUN apt-get install -yq curl git build-essential libpq-dev postgresql-client
RUN curl -sL https: //deb.nodesource.com/setup | bash - && apt-get install -yq nodejs
RUN npm -g install npm@latest-2 # instalujemy node.js i npm
RUN mkdir /up-app # tworzymy katalog dla aplikacji
ADD Gemfile /up-app/Gemfile # Dodaje Gemfile i Gemfile.lock
ADD Gemfile.lock /up-app/Gemfile.lock
WORKDIR /up-app # Wykonuje `cd` do wskazanego katalogu
RUN bundle install # instaluje gemy
EXPOSE 3000
CMD /bin/bash
12. docker-compose.yml - opis stacku aplikacji
version: ‘2' # wykorzystujemy drugi, nowszy sposób zapsiu pliku
volumes: # sekcja wolumenów
app_data:
services:
postgres_data: # kontener z bazą danych
container_name: up_postgres_data
image: busybox
volumes: # współdzelone pliki i foldery
- /var/lib/postgresql/data
postgres:
container_name: up_postgres
restart: on-failure # kiedy restartować
image: postgres:9.4.4
volumes_from:
- postgres_data
ports:
- “5432:5432" # porty do bindowania
environment: # zmienne środowiskowe używane przez bazowy image
POSTGRES_DB: 'up_docker_development'
POSTGRES_USER: 'up_docker'
POSTGRES_PASSWORD: 'up_docker'
app:
container_name: up_app
build: # opis w jaki sposób ma zostać zbudowany kontener
context: ../ ../.
dockerfile: ./devops/docker/Dockerfile
image: up_app
command: bash -c "rm -rf tmp/pids/server.pid && rails server -b ‘0.0.0.0'"
# komenda wykonywana przez nasz kontener
restart: on-failure
ports:
- "3000:3000"
volumes:
- ../ ../.:/up-app
links: # jakie konenery mają być widoczne przez kontener aplikacji
- postgres:postgres
tty: true
stdin_open: true
Struktura projektu
.
├── Gemfile
├── Gemfile.lock
├── app
├── bin
├── config
├── config.ru
├── db
├── devops
│ └── docker
│ ├── Dockerfile
│ └── docker-compose.yml
├── lib
├── log
├── public
└── vendor
14. Podstawowe polecenia
docker-compose build - buduje aplikację i jej zależności
docker-compose up - uruchamia aplikację i zależności
docker-compose status - pokazuje status kontenerów i zależności
docker exec - wykonuje polecenie na uruchomionym kontenerze
docker-compose run - wykonuje polecenie uruchamiając nowy kontener
docker attach - podłącza się do działającego kontenera
docker-compose logs oraz docker logs - podgląd logów z kontenerów
docker-compose stop - wyłącza kontenery
docker-compose down - wyłącza i USUWA kontenery
14
15. docker-compose build - budowanie aplikacji i jej zależności
# tkaczu @ TkaczBook in ~/Workspace/TSH/Uszanowanko/Docker on git:master x
[23:24:48]
$ docker-compose -f devops/docker/docker-compose.yml build
postgres_data uses an image, skipping
postgres uses an image, skipping
Building app
Step 1 : FROM ruby:2.3.1
Step 2 : MAINTAINER "Bartosz 'tkaczu' Tkaczewski"
Step 3 : RUN apt-get update -qq && apt-get upgrade -qq
Step 4 : RUN apt-get install -yq curl git build-essential libpq-dev postgresql-
client
Step 5 : RUN curl -sL https: //deb.nodesource.com/setup | bash - && apt-get install
-yq nodejs
Step 6 : RUN npm -g install npm@latest-2
Step 7 : RUN mkdir /up-app
Step 8 : ADD Gemfile /up-app/Gemfile
Step 9 : ADD Gemfile.lock /up-app/Gemfile.lock
Step 10 : WORKDIR /up-app
Step 11 : RUN bundle install
Step 12 : EXPOSE 3000
Step 13 : CMD /bin/bash
Removing intermediate container 63f26b37685c
Successfully built f5ddcf5cd5c1
16. docker-compose up - uruchamia aplikację i jej zależności
# tkaczu @ TkaczBook in ~/Workspace/TSH/Uszanowanko/Docker on git:master x [23:32:09]
$ docker-compose -f devops/docker/docker-compose.yml up -d
Creating network "docker_default" with the default driver
Creating volume "docker_app_data" with default driver
Pulling postgres_data (busybox:latest) ...
latest: Pulling from library/busybox
56bec22e3559: Pull complete
Digest: sha256:29f5d56d12684887bdfa50dcd29fc31eea4aaf4ad3bec43daf19026a7ce69912
Status: Downloaded newer image for busybox:latest
Pulling postgres (postgres:9.4.4) ...
9.4.4: Pulling from library/postgres
Digest: sha256:2380a12b9a90724e278b0fa4e4173774bb729752b7fc85bacb4881d942931d3e
Status: Downloaded newer image for postgres:9.4.4
Creating up_postgres_data
Creating up_postgres
Creating up_app
23. docker attach - podłącza się do działającego kontenera
# tkaczu @ TkaczBook in ~/Workspace/TSH/Uszanowanko/Docker on git:master x [0:40:40]
$ docker attach up_app
Started GET "/" for 192.168.99.1 at 2016-10-23 22:41:55 +0000
Cannot render console from 192.168.99.1! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by PostsController#index as HTML
Post Load (0.4ms) SELECT "posts".* FROM "posts"
Rendered posts/index.html.erb within layouts/application (1.6ms)
Completed 200 OK in 102ms (Views: 100.7ms | ActiveRecord: 0.4ms)
Started GET "/posts/new" for 192.168.99.1 at 2016-10-23 22:44:11 +0000
Cannot render console from 192.168.99.1! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by PostsController#new as HTML
Rendered posts/_form.html.erb (34.7ms)
Rendered posts/new.html.erb within layouts/application (62.5ms)
Completed 200 OK in 247ms (Views: 240.9ms | ActiveRecord: 2.1ms)
Started GET "/assets/ckeditor/config.js?t=FB9E" for 192.168.99.1 at 2016-10-23 22:44:12 +0000
Cannot render console from 192.168.99.1! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Started GET "/posts" for 192.168.99.1 at 2016-10-23 22:57:11 +0000
Cannot render console from 192.168.99.1! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by PostsController#index as HTML
[2, 11] in /up-app/app/controllers/posts_controller.rb
2: before_action :find_post, only: [:edit, :update, :show, :delete]
3:
4: # Index action to render all posts
5: def index
6: byebug
=> 7: @posts = Post.all
8: end
9:
10: # New action for creating post
11: def new
(byebug) exit
Completed 500 Internal Server Error in 51610ms (ActiveRecord: 0.0ms)
SystemExit (exit):
app/controllers/posts_controller.rb:7:in `index'
Rendered /usr/local/bundle/gems/actionpack-4.2.6/lib/action_dispatch/middleware/templates/rescues/_source.erb (70.5ms)
Started GET "/assets/posts.self-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.css?body=1" for
192.168.99.1 at 2016-10-23 22:44:20 +0000
Cannot render console from 192.168.99.1! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
24. docker-compose logs -podgląd logów z kontenerów
# tkaczu @ TkaczBook in ~/Workspace/TSH/Uszanowanko/Docker on git:master x [1:03:40] C:1
$ docker-compose -f devops/docker/docker-compose.yml logs --follow --tail="10"
Attaching to up_app, up_postgres, up_postgres_data
up_app | [2016-10-23 23:02:49] INFO WEBrick ::HTTPServer#start: pid=7 port=3000
up_app |
up_app |
up_app | Started GET "/posts" for 192.168.99.1 at 2016-10-23 23:03:43 +0000
up_app | Cannot render console from 192.168.99.1! Allowed networks: 127.0.0.1, ::1,
127.0.0.0/127.255.255.255
up_app | ActiveRecord ::SchemaMigration Load (0.6ms) SELECT "schema_migrations".* FROM
"schema_migrations"
up_app | Processing by PostsController#index as HTML
up_app | Post Load (0.6ms) SELECT "posts".* FROM "posts"
up_app | Rendered posts/index.html.erb within layouts/application (10.3ms)
up_app | Completed 200 OK in 2695ms (Views: 2678.0ms | ActiveRecord: 3.5ms)
up_postgres_data exited with code 0
up_postgres | LOG: database system is ready to accept connections
up_postgres | LOG: autovacuum launcher started
up_postgres | LOG: received smart shutdown request
up_postgres | LOG: autovacuum launcher shutting down
up_postgres | LOG: shutting down
up_postgres | LOG: database system is shut down
up_postgres | LOG: database system was shut down at 2016-10-23 22:40:30 UTC
up_postgres | LOG: MultiXact member wraparound protections are now enabled
up_postgres | LOG: database system is ready to accept connections
up_postgres | LOG: autovacuum launcher started
25. docker logs - podgląd logów z konkretnego kontenera
# tkaczu @ TkaczBook in ~/Workspace/TSH/Uszanowanko/Docker on git:master x [1:04:51] C:1
$ docker logs up_app --follow --tail="10"
[2016-10-23 23:02:49] INFO WEBrick ::HTTPServer#start: pid=7 port=3000
Started GET "/posts" for 192.168.99.1 at 2016-10-23 23:03:43 +0000
Cannot render console from 192.168.99.1! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
ActiveRecord ::SchemaMigration Load (0.6ms) SELECT "schema_migrations".* FROM "schema_migrations"
Processing by PostsController#index as HTML
Post Load (0.6ms) SELECT "posts".* FROM "posts"
Rendered posts/index.html.erb within layouts/application (10.3ms)
Completed 200 OK in 2695ms (Views: 2678.0ms | ActiveRecord: 3.5ms)
Started GET "/posts/1" for 192.168.99.1 at 2016-10-23 23:06:44 +0000
Cannot render console from 192.168.99.1! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by PostsController#show as HTML
Parameters: {"id" =>"1"}
Post Load (0.3ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" = $1 LIMIT 1 [["id", 1]]
Rendered posts/show.html.erb within layouts/application (0.7ms)
Completed 200 OK in 109ms (Views: 97.9ms | ActiveRecord: 0.5ms)
Started GET "/posts/new" for 192.168.99.1 at 2016-10-23 23:06:54 +0000
Cannot render console from 192.168.99.1! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by PostsController#new as HTML
Rendered posts/_form.html.erb (17.4ms)
Rendered posts/new.html.erb within layouts/application (23.7ms)
Completed 200 OK in 110ms (Views: 109.2ms | ActiveRecord: 0.0ms)
Started POST "/posts" for 192.168.99.1 at 2016-10-23 23:07:10 +0000
Cannot render console from 192.168.99.1! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by PostsController#create as HTML
Parameters: {"utf8" =>"✓", "authenticity_token" =>"gkd3UEQLg1J+I34uL2BOKqYH5JRMfO+3zz5ahKhlBiyow2NwRwOapRuxq/
st9PATsm01AWvALX47ekwJ0Ya6og ==", "post" =>{"title" =>"Nowy post", "body" =>"<p>Treść nowego posta </p>rn"}, "commit" =>"Create Post"}
(0.2ms) BEGIN
SQL (0.3ms) INSERT INTO "posts" ("title", "body", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["title",
"Nowy post"], ["body", "<p>Treść nowego posta </p>rn"], ["created_at", "2016-10-23 23:07:10.097025"], ["updated_at", "2016-10-23
23:07:10.097025"]]
(1.0ms) COMMIT
Redirected to http: //192.168.99.100:3000/posts/2
Completed 302 Found in 7ms (ActiveRecord: 1.5ms)
Started GET "/posts/2" for 192.168.99.1 at 2016-10-23 23:07:10 +0000
Cannot render console from 192.168.99.1! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by PostsController#show as HTML
Parameters: {"id" =>"2"}
Post Load (0.3ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" = $1 LIMIT 1 [["id", 2]]
Rendered posts/show.html.erb within layouts/application (0.2ms)
Completed 200 OK in 94ms (Views: 92.2ms | ActiveRecord: 0.3ms)
26. docker-compose down - wyłącza i USUWA(!!!) kontenery
# tkaczu @ TkaczBook in ~/Workspace/TSH/Uszanowanko/Docker on git:master x [1:36:49]
$ docker-compose -f devops/docker/docker-compose.yml down
Stopping up_app ... done
Stopping up_postgres ... done
Removing up_app ... done
Removing up_postgres ... done
Removing up_postgres_data ... done
Removing network docker_default
docker-compose stop - wyłącza kontenery
# tkaczu @ TkaczBook in ~/Workspace/TSH/Uszanowanko/Docker on git:master x [1:35:38]
$ docker-compose -f devops/docker/docker-compose.yml stop
Stopping up_app ... done
Stopping up_postgres ... done