Ciao a tutti!
Vorrei davvero iniziare subito a parlare dell'argomento, ma è meglio se racconto un po' la mia storia:
Introduzione
Sono un programmatore con esperienza nello sviluppo di applicazioni web front-end, scala/java e nodejs sul server.
Per molto tempo (esattamente da un paio di anni) ho pensato che Docker fosse una manna dal cielo e un ottimo strumento, e che ogni sviluppatore dovesse saperlo usare. Da qui deriva che ogni sviluppatore dovrebbe avere Docker installato sulla propria macchina locale. Anzi, parlando della mia opinione, date un'occhiata agli annunci di lavoro su hh. In quasi ogni secondo c'è un riferimento a Docker e se lo possedete, sarà un vantaggio competitivo 😉
Nel mio percorso ho incontrato molte persone, con atteggiamenti diversi verso Docker e la sua ecosistema. Alcuni dicevano che fosse uno strumento comodo, che garantiva la compatibilità tra piattaforme. Altri non capivano perché dovessero eseguire applicazioni in container e quale vantaggio ci fosse, altri ancora erano indifferenti e si limitavano a scrivere codice e tornare a casa — devo ammettere che li invidio 🙂
Motivi per l'uso
Perché ho usato Docker? Probabilmente per i seguenti motivi:
- esecuzione di database, il 99% delle applicazioni li utilizza
- esecuzione di Nginx per distribuire il front-end e fare proxy verso il back-end
- puoi impacchettare l'applicazione in un'immagine Docker, così la mia applicazione funzionerà ovunque ci sia Docker, il problema della distribuzione è già risolto
- discovery del servizio integrato, è possibile creare microservizi, ogni container (collegato a una rete comune) può facilmente comunicare con l'altro tramite alias, molto comodo
- è divertente creare un container e "giocarci" dentro.
Cosa non mi è mai piaciuto di Docker:
- per far funzionare la mia applicazione, ho bisogno di Docker sul server. E perché dovrei farlo, se le mie applicazioni funzionano su JRE o su Node.js e l'ambiente per loro è già presente nel server?
- se voglio eseguire la mia immagine (privata) assemblata localmente su un server remoto, ho bisogno di un mio repository Docker, devo avere un registry da qualche parte e devo anche configurare HTTPS, perché Docker CLI funziona solo tramite HTTPS. Oh cavolo... ci sono ovviamente opzioni, come salvare l'immagine localmente tramite
docker savee poi semplicemente trasferire l'immagine tramite scp… Ma richiede così tanto lavoro. Inoltre, sembra una soluzione "workaround" fino a quando non ho il mio repository. docker-composeÈ necessario solo per avviare i container. E basta. Non può fare nient'altro.Docker-composeha un sacco di versioni dei suoi file, la sua sintassi. Per quanto sia dichiarativo, non voglio leggere la loro documentazione. Non ne ho più bisogno altrove.- nella maggior parte dei casi, quando si lavora in team, le persone scrivono Dockerfile in modo molto scadente, non capiscono come funziona la cache, aggiungono nell'immagine tutto ciò che serve e non serve, ereditano immagini che non esistono su dockerhub o in repository privati, creano qualche
docker-composefile con database e non persistono nulla. Allo stesso tempo, gli sviluppatori dichiarano con orgoglio che docker è fantastico, che funziona tutto in locale e le risorse umane scrivono nelle offerte di lavoro: «Usiamo docker e abbiamo bisogno di un candidato con questa esperienza» - hanno pensieri costanti su come avviare in docker tutto e di più: postgresql, kafka, redis. Peccato che non tutto funzioni nei container, non tutto è facile da configurare e avviare. Sono supportati da sviluppatori esterni, non dai fornitori stessi. E a proposito, sorge subito una domanda: se i fornitori non si preoccupano di mantenere i loro prodotti in docker, forse sanno qualcosa di più?
- sorge sempre la questione della persistenza dei dati del container. E qui si pensa, devo semplicemente montare una directory dell'host oppure creare un volume docker o fare un data container che ora
deprecated? Если я монтирую директорию то мне нужно убедиться что uid и gid пользователя в контейнере соответствует id пользователя запустившего контейнер, иначе файлы созданные контейнером будут созданы с правами владельца root. Если используюvolumei dati verranno semplicemente creati in qualche/usr/*e ci sarà la stessa storia con uid e gid come nel primo caso. Se si avvia un componente di terze parti, si deve entrare nella documentazione e cercare risposta alla domanda: «in quali directory del container il componente scrive i file?»
Non mi è mai piaciuto dover armeggiare troppo con docker all'inizio: pensavo a come avviare i container, da quali immagini avviarmi, creavo Makefile che contenevano alias per lunghe comandi docker. Non sopportavo docker-compose, perché non volevo imparare un altro strumento dell'ecosistema docker. E docker-compose up mi ha stressato, soprattutto se c'erano anche build costruzioni, e non immagini già pronte. Tutto ciò che volevo davvero era semplicemente fare il prodotto in modo efficace e veloce. Ma non riuscivo a mettere in ordine l'uso di docker.
Introduzione ad Ansible
Recentemente (un paio di mesi fa), ho lavorato con un team DevOps, quasi ogni partecipante era negativo nei confronti di docker. Per motivi:
- docker modifica iptables (anche se si può disattivare in daemon.json)
- non utilizzeremo docker in produzione
- se il demone docker si arresta, allora di conseguenza si arrestano anche tutti i contenitori con l'infrastruttura
- non c'è bisogno di docker
- perché usare docker se ci sono Ansible e macchine virtuali
Nello stesso lavoro ho conosciuto un altro strumento: Ansible. Una volta ne avevo sentito parlare, ma non avevo mai provato a scrivere i miei playbook. Ora ho iniziato a scrivere i miei task e la mia visione è cambiata completamente! Perché ho capito: Ansible ha moduli per l'avvio degli stessi contenitori docker, la creazione di immagini, reti, ecc., e i contenitori possono essere avviati non solo localmente, ma anche su server remoti! La mia gioia non aveva limiti: ho trovato uno strumento DEGNO e ho buttato via i miei file Makefile e docker-compose, sostituiti da task yaml. Il codice è stato ridotto grazie all'uso di strutture tipo loop, when, ecc.
Docker per eseguire componenti esterni tipo database
Recentemente ho scoperto i tunnel SSH. Si è rivelato molto semplice 'inoltrare' la porta di un server remoto su una porta locale. Il server remoto può essere sia una macchina nel cloud, sia una macchina virtuale avviata in VirtualBox. Se io o un mio collega abbiamo bisogno di un database (o di qualche altro componente esterno), possiamo semplicemente avviare un server con quel componente e spegnerlo quando non serve. L'inoltro delle porte ha lo stesso effetto di un database eseguito in un contenitore docker.
Questo comando inoltra la mia porta locale su un server remoto con postgresql:
ssh -L 9000:localhost:5432 user@example.com
L'uso di un server remoto risolve il problema di sviluppo in team. Diversi sviluppatori possono utilizzare lo stesso server, non devono necessariamente sapere come configurare postgresql, districarsi con docker e altre complicazioni. Sul server remoto si può installare lo stesso database in docker, se è difficile installare una versione specifica. Tutto ciò di cui hanno bisogno gli sviluppatori è avere accesso SSH!
Ho recentemente letto che i tunnel SSH sono una funzionalità limitata di un normale VPN! È possibile semplicemente configurare OpenVPN o altre implementazioni VPN, impostare l'infrastruttura e metterla a disposizione degli sviluppatori. È davvero fantastico!
Fortunatamente, AWS, GoogleCloud e altri offrono un anno di utilizzo gratuito, quindi approfittatene! Costano poco se si spengono quando non vengono utilizzati. Mi sono sempre chiesto in quali situazioni avrei bisogno di un server remoto come gcloud, sembra che l'abbia trovato.
Come macchina virtuale in locale si può usare lo stesso Alpine che è attivamente utilizzato nei container docker. O altri distribuzioni leggere per far avviare la macchina più velocemente.
In sintesi: è possibile e necessario eseguire database e altre infrastrutture su server remoti o in virtualbox. Non ho bisogno di docker per questi scopi.
Un po' su immagini docker e distribuzione
Ho già scritto in cui volevo far capire che l'uso delle immagini docker non fornisce alcuna garanzia. Le immagini docker servono solo per creare un container docker. Se ti impegni con un'immagine docker, significa che ti impegni all'uso dei container docker e rimarrai solo con loro.
Hai mai visto sviluppatori software che hanno portato i loro prodotti solo in immagini docker?
Il risultato della maggior parte dei prodotti è un file binario per una specifica piattaforma, che viene semplicemente aggiunto all'immagine docker ereditata dalla piattaforma richiesta. Non ti sei mai chiesto perché ci sono così tante immagini simili su dockerhub? Ad esempio, cerca nginx, vedrai centinaia di immagini da diverse persone. Queste persone non hanno sviluppato il nginx stesso, hanno semplicemente aggiunto il nginx ufficiale alla loro immagine docker con le proprie configurazioni per rendere più facile l'avvio dei container.
In generale, si può semplicemente conservare in tgz, se qualcuno avrà bisogno di eseguirlo in docker, può semplicemente aggiungere tgz nel Dockerfile, ereditare l'ambiente necessario e creare ulteriori funzionalità che non modificano l'applicazione stessa in tgz. Chiunque creerà un'immagine docker, saprà di cosa si tratta tgz e cosa serve per farla funzionare. Questo è esattamente come utilizzo docker.
In sintesi: non ho bisogno di un docker registry, userò qualche S3 o semplicemente uno storage di file tipo google drive/dropbox.
Docker in CI
Tutte le aziende in cui ho lavorato sono simili tra loro. Di solito, sono aziende di prodotto. Cioè hanno un'applicazione principale, uno stack tecnologico (magari un paio - tre linguaggi di programmazione).
Queste aziende utilizzano Docker sui loro server dove viene eseguito il processo CI. La domanda è: perché è necessario costruire progetti in un contenitore Docker sui propri server? Perché non preparare semplicemente l'ambiente per la compilazione, ad esempio scrivere un playbook Ansible che installerà le versioni necessarie di Node.js, PHP, JDK, copierà le chiavi SSH, ecc. sul server in cui avverrà la compilazione?
Ora capisco che è come spararsi ai piedi, perché Docker non offre alcun vantaggio con la sua isolamento. I problemi con CI in Docker con cui mi sono trovato sono:
- serve nuovamente un'immagine Docker per la compilazione. bisogna cercare un'immagine o scrivere il proprio Dockerfile.
- C'è il 90% di probabilità che sia necessario passare alcune chiavi SSH, dati sensibili che non si desidera scrivere nell'immagine Docker.
- il contenitore viene creato e muore, tutti i cache vengono persi con esso. La compilazione successiva dovrà riscaricare tutte le dipendenze del progetto, il che è lungo e inefficiente, e il tempo è denaro.
Gli sviluppatori non compilano progetti nei contenitori Docker (una volta ero un grande fan, ci tengo a sottolinearlo xD). In Java c'è la possibilità di avere più versioni e cambiarle con un solo comando a quella necessaria al momento. Lo stesso vale per Node.js, c'è nvm.
Conclusione
Ritengo che Docker sia uno strumento molto potente e flessibile, ed è proprio questo il suo difetto (suona strano, vero?). Con esso, le aziende si 'agganciano' facilmente, lo usano dove è necessario e dove non lo è. Gli sviluppatori avviano i loro contenitori, il loro ambiente, e poi tutto questo si trasferisce dolcemente nel CI, nella produzione. Il team DevOps scrive qualche bicicletta per avviare questi contenitori.
Utilizzate Docker solo nell' ultimissimo passaggio del vostro processo di lavoro, non portatelo nel progetto all'inizio. Non risolverà i vostri problemi aziendali. Sposterà solo i problemi a un ALTRO livello e offrirà le sue soluzioni, voi farete doppio lavoro.
Quando è necessario Docker: sono arrivato alla conclusione che Docker è molto utile nell'ottimizzare il processo stabilito, ma non nella costruzione delle funzionalità di base.
Se comunque avete deciso di utilizzare Docker, allora:
- siate estremamente cauti
- non imposte l'utilizzo di Docker agli sviluppatori
- localizzate il suo utilizzo in un solo posto, non spargetelo su tutti i repository con Dockerfile e docker-compose
PS:
- Recentemente mi sono imbattuto in E si dice che lavori molto bene con Ansible e consenta di uniformare il processo di creazione delle immagini (compresa l'immagine Docker)
Grazie per aver letto, vi auguro soluzioni trasparenti nei vostri affari e giornate lavorative produttive!
Fonte: habr.com
