Jak jsem se seznámil s Dockerem, co mě na začátku trápilo, proč je dobré si sestavovat vlastní Docker images a pár odkazů na mé Docker images.
Tento článek měl přijít už hodně dávno, ale já to stále a pořád dokola odkládal, no, znáte to. Moje první seznámení s Dockerem proběhlo vcelku nevinně. Zhruba před 2 lety jsem hledal technologii, která u nás nebyla tak rozšířená, abych zvýšil svoji hodnotu jako vývojář. Docker byl populární, hlavně na Twitteru, ale u nás se o tom zase tolik nepsalo a nevědělo, nebo alespoň já nevěděl.
Hipsterskou technologii jsem tedy měl, ale jak začít? Řekněmě, že jsem Linuxu tak nějak rozuměl. Zvládl jsem nainstalovat server, aby na něm běžel Nginx, PHP-FPM, nějaká databáze apod. Věděl jsem, že existují nějací uživatelé a ti mohou mít být ve více skupinách. Že na serveru jsou nějaké porty a že SSH běží na 22.
Když jsem si pročítal dokumentaci Dockeru, moc jsem tomu nerozuměl. To mě lákalo. Na druhou stranu, co myslí tím spustit službu v containeru? Co to je ten container? Ony ty služby mohou běžet odděleně? Co myslí tím odděleně? Absolutně jsem si neuměl představit, že 2 služby můžou běžet odděleně a defakto na sebe nevidět. Znalí linuxáři prominou, ale já byl v tomhle zelenáč.
Moje první pokusy byly poněkud naivní. Pochopitelně. Představa, že si udělám vlastní ekosystém containerů a budu slavný,
bylo skvělé, bohužel to takhle pojal každý. Tzn., že na začátku jsem spíše vykrádal cizí konfigurace (Dockerfile).
Nebylo to tak zlé, akorát jsem spojoval věci, co spojit nešli, ostatní Dockerfiles nebyly až na tolik kvalitní a
stále jsem nerozuměl všem těm magickým klíčovým slovům jako ADD
vs COPY
, VOLUME
, EXPOSE
, CMD
vs ENTRYPOINT
.
Dost mého zesměšňování, pojdmě si ukázat můj první Dockerfile.
Jelikož jsem používal (používám i nadále) Linux Mint, navíc se mi vždy líbila ideologie Debianu, můj Dockerfile vycházel z debian:jessie.
FROM debian:jessie
MAINTAINER Felix <sulcmil@gmail.com>
RUN whoami
RUN time
CMD /bin/bash
S čím jsem si byl jistý už od začátku byl MAINTAINER
, v tom jsem vynikal.
Pojďme si rozklíčovat co které slovo znamená.
FROM
- z jakého základního image náš image vychází (též nazývaný base image)MAINTAINER
- skvělý borec, tedy jáRUN
- příkaz, který se vykoná v rámci sestavovaní image (instalace, konfigurace, mazání, zkrátka cokoli)CMD
- příkaz, který se spustí při nastartování containeruDefakto takto by se dala shrnout celá nezbytná konfigurace. Můj pokus zjistit, kdo jsem (whoami
), může vypadat dost
pošetile, ale byl jsem rád, že se v té consoli objevuje něco pěkného.
Znalí docker-ninjové mohou podotknout, proč se tam opakuje klíčové slovo RUN
a neprovede se zřetězení volaných příkazů.
No řekněme, že na začátek toho bylo až až.
Neoptimálně navržený Dockerfile bychom měli, nyní je potřeba ho sestavit, resp. zbuildit.
docker build -t <name> .
Zbuilděním Dockerfile vznikne image, který když se spustí, tak se z něho stane container, tedy bežící container, dá-li
linuxový bůh. Příkaz docker build
je potřeba spouštět v adresáři, kde máme daný Dockerfile, případně předat správnou
cestu.
Jak se spustí container?
docker run <name>
Tohle stačí, abychom z Docker image vytvořili container. Jak snadné. Jenže! Konzole nereaguje, můžu tam něco psát, ale nevypadá to OK. Občas se container rovnou odpojí (detached). Takhle vypadá ten slavný Docker? To jsem čekal něco lepšího.
Po bádáni v dokumentaci jsem odhalil 2 nezbytně důležité atributy, bez kterých jakékoli hrátky s Dockerem postrádají smysl.
docker run -it <name>
Znamená to vlastně, že chceme nechat otevřený vstup (STDIN
) a taktéž alokovanou pseudo-tty (dokumentace).
Hustý co? Alokovaná pseudo-tty, resp. teletypewriter. Najs.
Z aktuálně přihlášeného contaieru se dostaneme zkratkou CTRL+C
, resp. CTRL+D
. Zajímalo mě ale, kam se ty containery poděly.
Startuju je, odhlašuju se z nich, kde jsou teď? Běží ještě?
List běžících containeru se dá dostat takto:
docker ps
Pokud bychom potřebovali všechny, tzn i neběžící, je na to přepínač -a
.
docker ps -a
Po chvilce nepozorovaného hraní a zkoušení máme v PC pěkný bordel. Všude se válejí containery, image a nebo dokonce pohozené služby. Je čas to uklidit.
Smazat jednotlivý neběžící container se dá takto:
docker rm <container>
Pokud chceme smazat svůj zbuilděný image, vypadá to dost podobně:
docker rmi <image>
No jo, ale mazat takhle 20 containerů, to se člověku nechce. Naštěstí existuje pár pomocných scriptů.
docker rm $(docker ps -a -q);
Aktuálně tedy zvládám zbuildit image, spustit container, smazat neaktivní, už je tedy čas do něho nainstalovat pořádný nástroj. Ano, PHP.
FROM debian:jessie
RUN apt-get install php5-cli
CMD /bin/bash
Všechno vypadá na první pohled správně, ale po chvilce buildění na mě vyskočila hláška.
E: Unable to locate package php5-cli
The command '/bin/sh -c apt-get install php5-cli' returned a non-zero code: 100
Sakra, on Debian Jessie nemá k dispozici tenhle balíček? Koukám jako blázen na jejich balíčkový portál a tam je (https://packages.debian.org/jessie/php5-cli).
Dalo mi dlouho než jsem zjistil, že base image na Docker hubu je ořezaný až na kost, aby zabíral co nejméně místa.
Jo, to dává smysl. Musíme předtím natáhnout aktuální meta informace o balíčcích (apt-get update
).
FROM debian:jessie
RUN apt-get update
RUN apt-get install php5-cli
CMD /bin/bash
Paráda, nejdříve to stahuje metadata a teď to jde instalovat. Sakra, nová chyba.
Do you want to continue? [Y/n] Abort.
The command '/bin/sh -c apt-get install php5-cli' returned a non-zero code: 1
Debian se mi asi snaží říct, abych potvrdil instalaci těchto balíčků. Jenže jak to mám udělat, když se to buildí autonomně.
Neexistuje nějaké automatické povolení? Existuje (apt-get install -y <package>
).
FROM debian:jessie
RUN apt-get update
RUN apt-get install -y php5-cli
CMD /bin/bash
Heuréka!
docker build -t web .
docker run -it web
Výsledný stav, jsem přihlášený do containeru a PHP je nainstalováno.
root@5598c7c895ff:/# php -v
PHP 5.6.30-0+deb8u1 (cli) (built: Feb 8 2017 08:50:21)
Copyright (c) 1997-2016 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies
with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2016, by Zend Technologies
root@5598c7c895ff:/#
Někdy přístě zkusím popsat jak jsem propojoval více containerů, jak jsem do nich namountoval data nebo hrál si s portama.
Pomalým bádáním a zkoumáním se dá tomu Dockeru přijít na chuť. Určitě stojí za vyzkoušení. Svět celkem rychle směřuje k pohodlně virtualizaci a containerizaci. Proč na to nevyužít zrovna Docker, pořád je to dost hipster technologie.
Dnes už je tolik materiálů, návodů a prošlapaných cest. Já v tom tenkrát viděl hlavně velkou výzvu, že budu umět něco, co není úplně běžné. Řekněmě, že jsem si připadal blbě, když se banda 10 letých dětí baví ve frontě do mekáče o PHP. No dobře, asi jim nebylo 10, ale já je tak viděl. Chtělo to novou hračku / výzvu.
Za ty 2 roky co s Dockerem dělám jsem na něm postavil desítky aplikací, stránek, stacků a to jsem o něm nevěděl vůbec nic. Od menších jednoúčelových, přes střední, až po celé konfigurace serverů s X službami a Y různými API. V posledním půl roce jsem rozjel celkem 5 GitLabů s GitLab CI kompletně na Dockeru, byl to ze začátku porod, hlavně s Docker runnerama v GitLab CI.
Trvalo mi 1 rok, než jsem si vyladil svůj lokální vývoj kompletně postavený na Dockeru, který jsem, když byl hotový téměř zahodil. Dost času z toho zabrala konfigurace xdebugu a PhpStormu. Pak příjde podpora remote PHP interpreta, no nenasr...? Určitě toho nelituju, protože mi to dalo odpovědi na všechny mé otázky.
Jelikož mám rád opensource, tak je 99% těchto Docker images dostupných na Githubu pod organizací Dockette. Třeba vás v něčem inspirují a vyburcují k budování vlastních sestav, to bych si moc přál.
Nejzajímavěší úlovky jsou:
Také jsem během práce s Dockerem dal do kupy (i kopčil) pár bash aliasů, které zlehčují použití.
Více na Gistu: https://gist.github.com/f3l1x/4c3bb59397d976ac83f0
# ------------------------------------
# Docker alias and function
# ------------------------------------
# Get latest container ID
alias dl="docker ps -l -q"
# Get container process
alias dps="docker ps"
# Get process included stop container
alias dpa="docker ps -a"
# Get images
alias di="docker images"
# Get container IP
alias dip="docker inspect --format '{{ .NetworkSettings.IPAddress }}'"
# Run deamonized container, e.g., $dkd base /bin/echo hello
alias dkd="docker run -d -P"
# Run interactive container, e.g., $dki base /bin/bash
alias dki="docker run -i -t -P"
# Execute interactive container, e.g., $dex base /bin/bash
alias dex="docker exec -i -t"
# Stop all containers
dstop() { docker stop $(docker ps -a -q); }
# Remove all containers
drm() { docker rm $(docker ps -a -q); }
# Stop and Remove all containers
alias drmf='docker stop $(docker ps -a -q) && docker rm $(docker ps -a -q)'
# Remove all images
dri() { docker rmi $(docker images -q); }
# Remove all <none> images
drin() { docker rmi -f $(docker images --filter "dangling=true" -q); }
# Dockerfile build, e.g., $dbu tcnksm/test
dbu() { docker build -t=$1 .; }
# Show all alias related docker
dalias() { alias | grep 'docker' | sed "s/^\([^=]*\)=\(.*\)/\1 => \2/"| sed "s/['|\']//g" | sort; }
V neposlední řadě už 2 roky okupuji doménu dckr.cz, kde je přeložený návod jak nainstalovat Docker na Debian Jessie. S touto doménou je spárovaná organizace na dckrfile na Githubu. Cílem je dát nováčkům nějaký pohled na Docker, pomoci jim pochopit, jak Docker funguje a na co ho mohou využít. De facto Q&A.
Těším se na feedback do komentářů, moc rád si poslechnu váš Docker příběh.