Salut tuturor!
Mi-ar plăcea foarte mult să încep direct cu subiectul, dar ar fi mai corect să povestesc puțin despre istoricul meu:
Introducere
Sunt programator cu experiență în dezvoltarea de aplicații frontend de tip single-page, scala/java și nodejs pe server.
De mult timp (deja cu siguranță vreo doi-trei ani), am avut părerea că Docker este o minune cerescă și o unealtă foarte tare, iar fiecare developer ar trebui să știe să o folosească. Și de aici rezultă că fiecare developer ar trebui să aibă Docker instalat pe mașina locală. Ce să mai vorbesc despre părerea mea, aruncați o privire la anunțurile de muncă postate pe hh. În fiecare a doua există o mențiune despre Docker și dacă stăpâniți acest instrument — va fi un avantaj competitiv pentru dumneavoastră 😉
Pe parcursul călătoriei mele, m-am întâlnit cu mulți oameni, fiecare având o părere diferită despre Docker și ecosistemul său. Unii spuneau că este un lucru convenabil care garantează cross-platform. Alții nu înțelegeau de ce ar trebui să ruleze în containere și care este beneficiul, altele erau complet indiferente și nu își făceau griji (pur și simplu scriau cod și plecau acasă — îi invidiez, de altfel 🙂 )
Motivele utilizării
De ce am folosit Docker? Probabil din următoarele motive:
- lansarea bazei de date, 99% dintre aplicații folosesc baze de date
- lansarea nginx pentru a distribui frontendul și a face proxy pe backend
- pot împacheta aplicația într-o imagine Docker, astfel aplicația mea va funcționa oriunde există Docker, problema distribuției este deja rezolvată
- descoperire de servicii din cutie, se pot face microservicii, fiecare container (conectat la o rețea comună) poate accesa ușor altul prin alias, foarte convenabil
- este interesant să creezi un container și să te „joci” în el.
Ce nu mi-a plăcut niciodată la Docker:
- pentru ca aplicația mea să funcționeze, am nevoie de Docker pe server. Dar de ce mi-ar trebui asta dacă aplicațiile mele funcționează pe jre sau pe nodejs și mediul pentru ele este deja pe server?
- dacă vreau să rulez propria imagine (privată) construită local pe un server la distanță, am nevoie de propriul meu repository Docker, trebuie să existe un registry undeva și trebuie să configurez https, deoarece Docker cli funcționează doar prin https. Oh, Doamne… există opțiuni, desigur, să salvezi imaginea local prin
docker saveși prin scp doar să transferi imaginea... Dar asta implică multe mișcări. Și, în plus, pare o soluție "de compromis" până nu va apărea propriul repository. docker-compose. El este necesar doar pentru a rula containere. Atât. Nu poate face nimic mai mult.Docker-composeare o mulțime de versiuni ale fișierelor sale, cu propriul său sintaxă. Oricât de declarat ar fi, nu vreau să citesc documentația lor. Nu am nevoie de ea niciunde altundeva.- în muncă în echipă, majoritatea oamenilor scriu Dockerfile foarte prost, nu înțeleg cum se utilizează cache-ul, adaugă în imagine tot ce e necesar și ce nu, moștenesc imagini care nu sunt pe dockerhub sau în un repository privat, creează anumite
docker-composefișiere cu baze de date și nimic nu persistă. În același timp, dezvoltatorii afirmă cu mândrie că docker este grozav, că le funcționează totul local și HR-ul scrie important în anunțurile de angajare: „Folosim docker și avem nevoie de un candidat cu această experiență”. - sunt mereu bântuit de gânduri despre a ridica în docker tot și toate: postgresql, kafka, redis. Din păcate, nu totul funcționează încontainere, nu totul este ușor de configurat și de pornit. Acestea sunt susținute de dezvoltatori terți, nu de proprii furnizori. Și, între noi fie vorba, apare imediat întrebarea, de ce furnizorul nu își face griji cu privire la menținerea produselor sale în docker, poate știu ceva?
- apare întotdeauna întrebarea despre persistența datelor din container. Și aici te gândești, ar trebui să îmi montezi pur și simplu un director gazdă sau să creezi un volum docker sau să fac un container de date care acum
este deprecated? Если я монтирую директорию то мне нужно убедиться что uid и gid пользователя в контейнере соответствует id пользователя запустившего контейнер, иначе файлы созданные контейнером будут созданы с правами владельца root. Если используюvolumatunci datele vor fi create pur și simplu într-un anumit/usr/*și va fi aceeași poveste cu uid și gid ca în primul caz. Dacă pornești un component terță parte, trebuie să studiezi documentația și să cauți răspunsul la întrebarea: „în ce directoare ale containerului componenta scrie fișiere?”
Întotdeauna mi-a displăcut că trebuie să mă ocup prea mult de docker. în etapa inițială: îmi inventam cum să rulez containere, din ce imagini să pornesc, făceam Makefile-uri care conțineau aliasuri pentru comenzi docker lungi. Nu suportam docker-compose, pentru că nu voiam să învăț încă un instrument din ecosistemul docker. Și docker-compose up mă enerva, mai ales dacă mai întâlneam build construcții, și nu imagini deja construite. Tot ce voiam cu adevărat era să fac produsul eficient și rapid. Dar nu puteam deloc să-mi pun în ordine utilizarea docker-ului.
Întâlnirea cu Ansible
Recent (about three months ago), I worked with a DevOps team, almost every member of which had a negative attitude towards Docker. The reasons were:
- Docker modifies iptables (although it can be disabled in daemon.json)
- Docker is buggy, and we won't run it in production
- if the Docker daemon crashes, all containers with infrastructure crash as well
- there is no need for Docker
- why use Docker if we have Ansible and virtual machines
At the same job, I got acquainted with another tool — Ansible. I had heard about it before but never tried writing my own playbooks. Now I've started writing my tasks and my perspective changed completely! Because I realized: Ansible has modules for launching the same Docker containers, building images, networks, etc., and containers can be launched not only locally but also on remote servers! My excitement knew no bounds — I found a PROPER tool and threw away my Makefile and Docker-compose files, which were replaced with YAML tasks. The code was reduced due to constructs like loop, when, etc.
Docker for running third-party components like databases
Recently, I got to know SSH tunnels. It turned out that it's very easy to "forward" a port from a remote server to a local port. The remote server can be a cloud machine or a virtual machine running in VirtualBox. If I or my colleague need a database (or some other third-party component), we can simply start the server with that component and shut it down when it's not needed. Port forwarding has the same effect as having a database running in a Docker container.
This command forwards my local port to a remote server with PostgreSQL:
ssh -L 9000:localhost:5432 user@example.com
Using a remote server addresses the problem of teamwork development. Such a server can be used by several developers at once; they don’t need to know how to set up PostgreSQL, deal with Docker, or other intricacies. On the remote server, the same database can be installed inside Docker if a specific version is difficult to get. All that developers will need is SSH access!
I recently read that SSH tunnels are a limited functionality compared to a regular VPN! You can simply set up OpenVPN or other VPN implementations, configure the infrastructure, and make it available to developers. It's so cool!
Din fericire, AWS, GoogleCloud și altele oferă un an de utilizare gratuită, așa că profitați de ele! Sunt foarte ieftine dacă le folosiți doar atunci când aveți nevoie. M-am întrebat întotdeauna pentru ce mi-ar trebui un server remote de tip gcloud, pare că am găsit răspunsul.
Ca mașină virtuală pe local, puteți folosi același Alpine care este folosit activ în containerele docker. Sau alte distribuții ușoare pentru a încărca mai repede mașina.
Concluzie: este bine să rulați baze de date și alte elemente de infrastructură pe servere remote sau în virtualbox. Nu am nevoie de docker pentru aceste scopuri.
Puțin despre imaginile docker și distribuție
Am mai scris în care am vrut să subliniez că utilizarea imaginilor docker nu oferă nicio garanție. Imaginile docker sunt doar pentru a crea un container docker. Dacă depinzi de o imagine docker, înseamnă că depinzi de utilizarea containerelor docker, și vei fi limitat la acestea.
Ați văzut vreodată dezvoltatori de software care și-au portat produsele doar în imagini docker?
Rezultatul majorității produselor este fișiere binare pentru o anumită platformă; acestea sunt adăugate pur și simplu în imaginea docker care moștenește platforma dorită. Nu v-ați întrebat de ce există atât de multe imagini asemănătoare în dockerhub? Introduceți de exemplu nginx, veți vedea 100500 imagini de la diferite persoane. Aceștia nu au dezvoltat nginx, ci doar au adăugat nginx-ul oficial în imaginea lor docker și l-au condimentat cu configurațiile proprii pentru a facilita lansarea containerelor.
În general, se poate stoca pur și simplu în tgz; dacă cineva are nevoie să ruleze asta în docker, să adauge tgz în Dockerfile, să moștenească mediul necesar și să creeze soluții suplimentare care nu schimbă aplicația din tgz. Cel care va crea imaginea docker va ști ce este tgz-ul și ce are nevoie pentru funcționare. Așa folosesc eu docker.
Concluzie: nu am nevoie de un registru docker, voi folosi un serviciu S3 sau un simplu spațiu de stocare de tip google drive/dropbox.
Docker în CI
Toate companiile în care am lucrat sunt similare între ele. Ele sunt de obicei companii de produs. Adică au o aplicație specifică, un set de tehnologii (poate două-trei limbaje de programare).
Aceste companii folosesc Docker pe serverele lor, unde se desfășoară procesul CI. Întrebarea este: de ce este necesar să construiești proiecte într-un container Docker pe serverele tale? De ce să nu pregătești pur și simplu un mediu de compilare, de exemplu să scrii un playbook Ansible care să instaleze versiunile necesare de Node.js, PHP, JDK, să copieze cheile SSH etc. pe serverul unde se va desfășura compilarea?
Acum înțeleg că este ca o auto-sabotare, deoarece Docker nu aduce niciun profit prin izolarea sa. Problemele cu CI în Docker cu care m-am confruntat sunt:
- din nou este nevoie de o imagine Docker pentru compilare. Trebuie să cauți o imagine sau să scrii propriul tău Dockerfile.
- 90% din cazuri va trebui să creezi și să folosești chei SSH, date sensibile pe care nu vrei să le incluzi în imaginea Docker.
- containerul se creează și moare, toate cache-urile se pierd odată cu el. Următoarea compilare va descărca din nou toate dependențele proiectului, ceea ce este lent și ineficient, iar timpul înseamnă bani.
Dezvoltatorii nu compilează proiecte în containere Docker (am fost cândva un fan, dar acum îmi pare rău că am fost așa xD). În Java există posibilitatea de a avea mai multe versiuni și de a schimba cu o singură comandă la cea de care ai nevoie acum. La fel este și în Node.js, există nvm.
Ieșire
Consider că Docker este un instrument foarte puternic și flexibil, ceea ce reprezintă un dezavantaj (sună ciudat, nu-i așa?). Cu ajutorul său, companiile se „beau” ușor, folosindu-l unde trebuie și unde nu. Dezvoltatorii își lansează containerele, un anumit mediu de dezvoltare, apoi totul se îmbină treptat în CI și producție. Echipa DevOps scrie diverse soluții pentru a rula aceste containere.
Folosiți Docker doar în cea mai recentă etapă a fluxului vostru de lucru, nu-l introduceți în proiect de la început. Nu va rezolva problemele voastre de afaceri. Va muta doar problemele la UN ALT nivel și va oferi propriile soluții, iar voi veți face un dublu efort.
Când este necesar Docker: am ajuns la concluzia că Docker este foarte bun pentru optimizarea procesului stabilit, dar nu pentru construirea funcționalității de bază.
Dacă totuși ați decis să folosiți Docker, atunci:
- fiți extrem de prudenți
- nu impuneți utilizarea Docker dezvoltorilor
- localizați utilizarea lui într-un singur loc, nu dispersați Dockerfile-ul și docker-compose-ul în toate repositoarele
PS:
- Recent, am dat peste Și se spune că funcționează foarte bine cu Ansible și permite unificarea procesului de construire a imaginilor (inclusiv imaginea Docker)
Mulțumesc că ați citit până la final, vă doresc soluții transparente în afacerile voastre și zile de muncă productive!
Sursa: habr.com
