Ciao a tutti!
Vorrei veramente iniziare subito con l'argomento, ma è più giusto raccontare un po' della mia storia.
Introduzione
Sono un programmatore con esperienza nello sviluppo di applicazioni web single-page, scala/java e nodejs sul server.
Per molto tempo (sicuramente un paio di anni) ho pensato che docker fosse un dono del cielo, un ottimo strumento che ogni sviluppatore dovrebbe sapere utilizzare. Da ciò ne deriva che ogni sviluppatore dovrebbe avere docker sul proprio computer locale. E non parlo solo della mia opinione, date un'occhiata alle offerte di lavoro su hh. In ogni seconda c'è un riferimento a docker e se lo conoscete, sarà il vostro vantaggio competitivo 😉
Nel mio cammino ho incontrato molte persone con atteggiamenti diversi nei confronti di docker e della sua ecosistema. Alcuni dicevano che fosse una cosa comoda che garantiva portabilità. Altri non capivano perché dovessero avviarsi in contenitori e quale fosse il vantaggio, alcuni non se ne preoccupavano affatto e scrivevano semplicemente codice per tornare a casa — invidio, tra l'altro, questo approccio 🙂
Motivi per l'uso
Perché ho usato docker? Probabilmente per i seguenti motivi:
- avvio di database, il 99% delle applicazioni li utilizza
- avvio di nginx per servire il frontend e fare proxy verso il backend
- posso impacchettare l'applicazione in un'immagine docker, il che significa che la mia applicazione funzionerà ovunque ci sia docker, risolvendo subito il problema della distribuzione
- service discovery out of the box, posso realizzare microservizi, ogni contenitore (connesso a una rete comune) può facilmente raggiungere l'altro tramite alias, molto comodo
- è divertente creare un contenitore e "sperimentare" al suo interno.
Cosa non mi è mai piaciuto di docker:
- per far funzionare la mia applicazione, serve docker stesso sul server. E perché mai dovrei averne bisogno se le mie applicazioni funzionano su jre o nodejs e ci sono già ambienti per loro sul server?
- se voglio avviare la mia immagine (privata) assemblata localmente su un server remoto, ho bisogno di un repository docker, devo avere un registro operativo da qualche parte e inoltre devo configurare https, perché docker cli funziona solo con https. Accidenti… ci sono certamente opzioni, come salvare l'immagine localmente e
docker savee poi semplicemente trasferirla con scp… Ma sono tante le operazioni necessarie. E sembra anche una soluzione "workaround", finché non ho il mio repository. docker-compose. Serve solo per far partire contenitori. E basta. Non può fare nient'altro.Docker-composeha molte versioni dei suoi file, il suo sintassi. Per quanto dichiarativo possa essere, non voglio leggere la loro documentazione. Non mi servirà altrove.- lavorando in team, per la maggior parte, le persone scrivono Dockerfile in modo molto impreciso, non capiscono come viene gestita la cache, aggiungono nell'immagine tutto ciò che serve e non serve, ereditano da immagini che non si trovano in dockerhub o nel repository privato, creano file con database e non persistono nulla. Nel frattempo, gli sviluppatori affermano con orgoglio che docker è fantastico, loro funzionano tutto localmente e gli HR, è importante, lo scrivono nelle offerte: «Utilizziamo docker e abbiamo bisogno di un candidato con tale esperienza».
docker-composesono sempre perseguitato dal pensiero di avviare tutto e qualsiasi cosa in docker: postgresql, kafka, redis. Peccato che non tutti funzionino nei contenitori, non tutto è facile da configurare e avviare. Supportati da sviluppatori terzi, non dai venditori stessi. E, tra l'altro, sorge immediatamente la domanda: i fornitori non si preoccupano di mantenere i propri prodotti in docker, perché mai, forse sanno qualcosa? - c'è sempre la questione della persistenza dei dati del contenitore. E qui pensi, devo semplicemente montare una directory dell'host o creare un volume docker o fare un data container che ora
- significa che i dati verranno creati in qualche modo
deprecated? Если я монтирую директорию то мне нужно убедиться что uid и gid пользователя в контейнере соответствует id пользователя запустившего контейнер, иначе файлы созданные контейнером будут созданы с правами владельца root. Если используюvolumee ci sarà la stessa storia con uid e gid come nel primo caso. Se avvii un componente di terzi, devi leggere la documentazione e cercare la risposta alla domanda: «in quali directory del contenitore il componente scrive i file?»/usr/*Non mi è mai piaciuto dover perdere troppo tempo a giocarci con docker.
all'inizio : pensavo come avviare contenitori, 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. Emi infastidiva, specialmente se all'interno c'erano ancora docker-compose up costruzioni, e non immagini già pronte. Tutto ciò che volevo veramente era semplicemente produrre in modo efficace e veloce. Ma non riesco a mettere in ordine l'uso di docker. build Incontro con Ansible
Recentemente (tre mesi fa), ho lavorato con un team DevOps, quasi ogni partecipante era negativo verso docker per i seguenti motivi:
docker gestisce iptables (anche se si può disabilitare in daemon.json)
- docker gestisce iptables (anche se può essere disattivato in daemon.json)
- Non utilizzeremo Docker in produzione.
- Se il daemon di Docker fallisce, anche tutti i contenitori con l'infrastruttura smetteranno di funzionare.
- Non c'è bisogno di Docker.
- Perché usare Docker se esistono Ansible e macchine virtuali?
In quel lavoro ho incontrato anche un altro strumento: Ansible. Ne avevo già sentito parlare, ma non avevo mai provato a scrivere le mie playbook. Ora ho iniziato a scrivere i miei task e la mia visione è cambiata radicalmente! Ho capito che Ansible ha moduli per avviare contenitori Docker, costruire immagini, gestire reti, ecc., e che i contenitori possono essere avviati non solo localmente, ma anche su server remoti! La mia gioia era incontenibile: avevo trovato uno strumento VALIDO e ho abbandonato i miei file Makefile e docker-compose, sostituiti da task YAML. Il codice è stato semplificato grazie all'uso di costrutti come loop, when, ecc.
Docker per l'avvio di componenti esterni come i database.
Di recente, ho scoperto gli SSH tunnel. È risultato molto semplice 'esporre' una porta di un server remoto a una porta locale. Il server remoto può essere una macchina nel cloud o una macchina virtuale avviata in VirtualBox. Se io o qualche collega abbiamo bisogno di un database (o di un altro componente esterno), possiamo semplicemente avviare il server con quel componente e spegnerlo quando non serve più. L'esposizione delle porte ha lo stesso effetto di un database avviato in un contenitore Docker.
Questo comando espone la mia porta locale a un server remoto con PostgreSQL:
ssh -L 9000:localhost:5432 user@example.com
Utilizzare un server remoto risolve il problema della collaborazione nello sviluppo. Questo server può essere utilizzato da più sviluppatori contemporaneamente, senza la necessità che sappiano configurare PostgreSQL, gestire Docker e altre complessità. Sul server remoto è possibile installare lo stesso database in Docker, se si ha difficoltà a trovare una versione specifica. Tutto ciò di cui hanno bisogno gli sviluppatori è l'accesso SSH!
Ho recentemente letto che gli SSH tunnel sono funzionalità limitate rispetto a una normale VPN! Si può semplicemente configurare OpenVPN o altre implementazioni di VPN, impostare l'infrastruttura e metterla a disposizione degli sviluppatori. È davvero fantastico!
Fortunately, AWS, Google Cloud e altri offrono un anno di utilizzo gratuito, sfruttatelo! Costano pochissimo se vengono spenti quando non sono utilizzati. Mi sono sempre chiesto in quali casi avrei avuto bisogno di un server remoto come GCloud, e sembra che l'abbia trovato.
Come macchina virtuale locale, si può utilizzare la stessa Alpine, che è molto usata nei contenitori Docker. Oppure altre distribuzioni leggere per rendere più veloce l'avvio della macchina.
In sintesi: si possono e si devono avviare database e altri componenti infrastrutturali 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 comunicare che l'uso delle immagini Docker non offre alcuna garanzia. Le immagini Docker servono solo per creare contenitori Docker. Se ti affidi a un'immagine Docker, significa che sei vincolato all'uso di contenitori Docker e rimarrai solo con quelli.
Hai mai visto sviluppatori di software che portano i loro prodotti esclusivamente in immagini Docker?
Il risultato della maggior parte dei prodotti è un file binario per una determinata piattaforma, che viene semplicemente aggiunto all'immagine Docker, ereditando dalla piattaforma necessaria. Non ti sei mai chiesto perché ci siano così tante immagini simili su Docker Hub? Cerca, ad esempio, nginx, vedrai 100500 immagini da diverse persone. Queste persone non hanno sviluppato il vero nginx, ma hanno semplicemente aggiunto il nginx ufficiale alla loro immagine Docker e lo hanno arricchito con le proprie configurazioni per facilitare l'avvio dei contenitori.
In generale, si possono semplicemente archiviare in tgz, se qualcuno ha bisogno di avviarli in Docker, allora può aggiungere tgz al Dockerfile, ereditare dall'ambiente necessario e creare funzionalità aggiuntive che non alterano l'applicazione in tgz. Chi creerà l'immagine Docker saprà che cos'è quel tgz e di cosa ha bisogno per funzionare. È esattamente così che uso Docker.
In sintesi: non ho bisogno di un registro Docker, utilizzerò un S3 qualsiasi o semplicemente un sistema di archiviazione file come Google Drive/Dropbox.
Docker in CI
Tutte le aziende in cui ho lavorato sono simili tra loro. Sono per lo più aziende di prodotto. Hanno un'applicazione principale, un'unica stack tecnologico (forse un paio o tre linguaggi di programmazione).
Queste aziende utilizzano Docker sui loro server dove viene eseguito il processo CI. La domanda è: perché assemblare progetti all'interno di un contenitore Docker sui propri server? Perché non preparare semplicemente l'ambiente per l'assemblaggio, ad esempio scrivendo un playbook Ansible che installi le versioni necessarie di Node.js, PHP, JDK, copiando chiavi SSH, ecc. sul server dove avverrà l'assemblaggio?
Ora capisco che è un autogol, perché Docker non porta alcun profitto con la sua isolamento. I problemi con CI in Docker a cui ho dovuto far fronte:
- è di nuovo necessario un'immagine Docker per la build. bisogna cercare un'immagine o scrivere il proprio Dockerfile.
- 90% delle volte è necessario passare alcune chiavi SSH, dati sensibili che non si vogliono scrivere nell'immagine Docker.
- il container si crea e poi muore, tutti i cache si perdono con esso. la prossima build dovrà riscaricare tutte le dipendenze del progetto, il che richiede tempo e non è efficiente, e il tempo è denaro.
Gli sviluppatori non costruiscono progetti in container Docker (un tempo ero un grande fan, non so come dire, mi dispiace per il mio passato xD). In Java c'è la possibilità di avere più versioni e cambiarle con un comando a quella che serve in questo momento. Lo stesso vale per Node.js, ci sono strumenti come nvm.
Risultato
Ritengo che Docker sia uno strumento molto potente e flessibile, ma questo è un suo difetto (suona strano, vero?). Grazie a esso, le aziende si ‘aggiungono’ facilmente, utilizzandolo dove necessario e non necessario. Gli sviluppatori avviano i propri container, il proprio ambiente, e questo poi viene integrato nel CI e nella produzione. Il team DevOps scrive alcuni ‘cicli’ per avviare questi container.
Utilizza Docker solo nella fase finale del tuo flusso di lavoro, non portarlo nel progetto all'inizio. Non risolverà i tuoi problemi aziendali. Semplicemente sposterà i problemi su UN ALTRO livello e proporrà soluzioni, mentre farai lavoro doppio.
Quando è necessario Docker: sono arrivato alla conclusione che Docker è molto buono nell'ottimizzare il processo stabilito ma non nella costruzione della funzionalità di base.
Se decidi di usare Docker, allora:
- stai estremamente attento
- non imporre l'uso di Docker agli sviluppatori
- localizza il suo utilizzo in un solo posto, non distribuirlo in tutti i repository Dockefile e docker-compose.
PS:
- Recentemente mi sono imbattuto in e dicono che funzioni molto bene con Ansible e permette di unificare il processo di creazione delle immagini (comprese le immagini Docker).
Grazie per aver letto, ti auguro soluzioni trasparenti nei tuoi affari e giornate lavorative produttive!
Fonte: habr.com
