Hallo allemaal!
I really want to dive straight into the topic, but it’s better to share a little about my story first:
Inleiding
I am a programmer with experience in developing frontend single-page applications, Scala/Java, and Node.js on the server side.
For quite a while (definitely a couple of years), I held the opinion that Docker is a godsend and a really cool tool that every developer should know how to use. This implies that every developer should have Docker installed on their local machine. Forget about my opinion; just browse through the job listings on sites like hh. In every second one, there's a mention of Docker, and if you know it, it will be your competitive advantage 😉
Along my journey, I encountered many people with different attitudes towards Docker and its ecosystem. Some said it’s a handy tool that guarantees cross-platform compatibility. Others didn’t see the point of running in containers and what benefits it brought. Some didn’t care at all and simply wrote code and went home—I envy them, by the way 🙂
Reasons for use
Why did I use Docker? Probably for the following reasons:
- Running databases; 99% of applications utilize them.
- Running Nginx for serving frontend and proxying to backend.
- You can package your application into a Docker image, so my application will work anywhere Docker is present; the distribution problem is solved right away.
- Service discovery out of the box; you can create microservices, and each container (connected to a shared network) can easily reach another by alias, which is very convenient.
- It’s cool to create a container and 'play around' in it.
What I have always NOT liked about Docker:
- For my application to work, Docker itself is needed on the server. But why would I need that if my applications run on JRE or Node.js and the environment for them is already on the server?
- If I want to run my (private) locally built image on a remote server, I need my own Docker repository; I need a registry to be running somewhere, and I also need to set up HTTPS because the Docker CLI only works over HTTPS. Oh man... there are, of course, ways to save the image locally through
docker saveen gewoon het beeld via scp overzetten... Maar dat is zoveel gedoe. En het lijkt bovendien een 'hackerige' oplossing, totdat er een eigen repository is. docker-compose. Het is alleen nodig voor het starten van containers. En dat is het. Meer kan het niet.Docker-composeheeft een heleboel versies van zijn bestanden, zijn eigen syntaxis. Hoe declaratief het ook is, ik wil hun documentatie niet lezen. Ik heb die meer nergens anders nodig.- bij het werken in een team schrijven de meeste mensen de Dockerfile heel slordig, begrijpen niet hoe het cachewerkt, voegen alles wat nodig en niet nodig is aan het beeld toe, erven van beelden die niet op dockerhub of in een privé-repository staan, creëren een paar
docker-composebestanden met databases en doen niets om ze persistent te maken. Ondertussen verkondigen de ontwikkelaars trots dat docker geweldig is, dat alles lokaal werkt, en HR schrijft in vacatures: 'We gebruiken docker en we hebben een kandidaat nodig met die ervaring.' - krijg je constant de gedachte om alles in docker op te zetten: postgresql, kafka, redis. Jammer dat niet alles in containers werkt, niet alles gemakkelijk te configureren en op te starten is. Dit wordt ondersteund door externe ontwikkelaars, niet door de verkopers zelf. Trouwens, er rijst meteen de vraag waarom de verkopers zich niet druk maken over de ondersteuning van hun producten in docker, misschien weten ze iets?
- er rijst altijd de vraag over de persistentie van containerdata. En dan denk je, moet ik de hostdirectory gewoon koppelen of een docker volume creëren of een data container maken die nu
verouderd? Если я монтирую директорию то мне нужно убедиться что uid и gid пользователя в контейнере соответствует id пользователя запустившего контейнер, иначе файлы созданные контейнером будут созданы с правами владельца root. Если используюvolumedan worden de gegevens gewoon ergens gegenereerd/usr/*en zal het hetzelfde verhaal zijn met uid en gid als in het eerste geval. Als je een externe component start, moet je de documentatie goed doorlezen en het antwoord op de vraag zoeken: 'in welke directories van de container schrijft de component bestanden?'
Ik heb altijd een hekel gehad aan het feit dat ik te lang met docker moest rommelen. in de beginfase: bedacht ik hoe ik containers moest starten, van welke beelden ik moest opstarten, maakte ik Makefile's met aliassen voor lange docker-commando's. Ik kon docker-compose niet uitstaan omdat ik niet nog een tool uit het docker-ecosysteem wilde leren. En docker-compose up dat stoorde me, vooral als er ook nog eens build constructies waren en geen al gebouwde beelden. Alles wat ik echt wilde, was gewoon het product efficiënt en snel te maken. Maar ik kon het gebruik van docker op de een of andere manier niet goed organiseren.
Kennismaking met Ansible
Onlangs (ongeveer drie maanden geleden) heb ik samengewerkt met een DevOps-team waarvan bijna alle leden negatief stonden tegenover Docker. De redenen hiervoor zijn:
- Docker beheert iptables (hoewel dit kan worden uitgeschakeld in daemon.json)
- Docker is onbetrouwbaar en we zullen het niet in productie draaien
- Als de Docker-daemon crasht, vallen ook alle containers met infrastructuur uit
- Er is geen noodzaak voor Docker
- Waarom Docker als er Ansible en virtuele machines zijn?
Op dezelfde werkplek leerde ik ook een ander instrument kennen - Ansible. Ik had er ooit over gehoord, maar had nog geen eigen playbooks geschreven. Maar nu ben ik begonnen met het schrijven van mijn eigen taken en mijn visie is volledig veranderd! Omdat ik begreep: Ansible heeft modules om dezelfde Docker-containers, afbeelding builds, netwerken enz. uit te voeren, en containers kunnen zowel lokaal als op externe servers worden uitgevoerd! Mijn enthousiasme kende geen grenzen - ik had een ECHT goed instrument gevonden en mijn Makefile en Docker-compose-bestanden weggegooid, die nu waren vervangen door yaml-taken. De code werd verminderd door het gebruik van constructies zoals loop, when, enzovoorts.
Docker voor het uitvoeren van externe componenten zoals databases
Onlangs leerde ik over SSH-tunnels. Het bleek heel eenvoudig te zijn om een poort van een externe server naar een lokale poort door te sturen. De externe server kan een cloudmachine zijn of een virtuele machine die draait in VirtualBox. Als ik of een collega een database (of een andere externe component) nodig heeft, kunnen we gewoon de server met die component starten en deze afsluiten wanneer de server niet meer nodig is. Het doorsturen van poorten biedt hetzelfde effect als een database die draait in een Docker-container.
Dit commando stuurt mijn lokale poort door naar de externe server met PostgreSQL:
ssh -L 9000:localhost:5432 user@example.com
Het gebruik van een externe server lost het probleem van teamontwikkeling op. Meerdere ontwikkelaars kunnen deze server tegelijk gebruiken, ze hoeven niet te leren hoe ze PostgreSQL moeten configureren, zich bezig te houden met Docker en andere complicaties. Op de externe server kan dezelfde database in Docker worden geïnstalleerd als het moeilijk is om een specifieke versie te vinden. Alles wat ontwikkelaars nodig hebben, is SSH-toegang!
Recentelijk las ik dat SSH-tunnels een beperkte functionaliteit van een gewone VPN zijn! Je kunt eenvoudig OpenVPN of andere VPN-implementaties instellen, de infrastructuur configureren en deze ter beschikking stellen aan ontwikkelaars. Dat is toch geweldig!
Gelukkig bieden AWS, Google Cloud en anderen een jaar gratis gebruik aan, dus maak er gebruik van! Ze zijn goedkoop als je ze uitschakelt wanneer ze niet worden gebruikt. Ik heb altijd nagedacht over de doeleinden waarvoor ik een externe server zoals gcloud zou gebruiken, en het lijkt erop dat ik ze heb gevonden.
Als virtuele machine op de lokale server kun je hetzelfde Alpine gebruiken dat actief is in docker containers. Of andere lichte distributies zodat de machine sneller opstart.
Conclusie: je kunt en moet databases en andere infrastructurele zaken op externe servers of in VirtualBox draaien. Ik heb Docker niet nodig voor deze doeleinden.
Een beetje over docker images en distributie
Ik heb al geschreven waarin ik wilde overbrengen dat het gebruik van docker images geen enkele garantie biedt. Docker images zijn alleen nodig om een docker container te creëren. Als je vastloopt op een docker image, betekent dat dat je vastloopt op het gebruik van docker containers en dat je alleen met hen zult werken.
Heb je ooit gezien dat softwareontwikkelaars hun producten alleen in docker images porteren?
Het resultaat van de meeste producten zijn binaire bestanden voor een bepaald platform; deze worden gewoon toegevoegd aan de docker image die is afgeleid van het vereiste platform. Heb je je ooit afgevraagd waarom er zoveel vergelijkbare images op Docker Hub zijn? Zoek bijvoorbeeld naar nginx, je ziet 100500 images van verschillende mensen. Deze mensen hebben nginx zelf niet ontwikkeld, ze hebben gewoon de officiële nginx aan hun docker image toegevoegd en het zijn configuraties voor het gemak van het opstarten van containers.
Over het algemeen kun je het eenvoudig opslaan in tgz; als iemand het in docker wil draaien, laat ze dan tgz toevoegen in de Dockerfile, afgeleid van de juiste omgeving en extra functies creëren die de applicatie in tgz niet veranderen. Degene die de docker image zal maken, zal weten wat deze tgz is en wat hij nodig heeft om te werken. Dit is hoe ik docker gebruik.
Conclusie: ik heb geen docker registry nodig, ik zal gebruikmaken van een S3 of gewoon een bestandopslag zoals Google Drive/Dropbox.
Docker in CI
Alle bedrijven waarvoor ik heb gewerkt, lijken op elkaar. Ze zijn meestal productgerichte bedrijven. Dat wil zeggen, ze hebben één applicatie, één technologische stack (misschien een paar talen).
Deze bedrijven gebruiken Docker op hun servers waar het CI-proces draait. De vraag is: waarom projecten in een Docker-container op hun servers bouwen? Waarom gewoon geen omgeving voor de bouw voorbereiden, bijvoorbeeld een Ansible-playbook schrijven dat de benodigde versies van Node.js, PHP, JDK installeert en SSH-sleutels enz. naar de server kopieert waar de bouw plaatsvindt?
Nu begrijp ik dat dit jezelf in de voet schieten is, omdat Docker geen voordeel biedt met zijn isolatie. Problemen met CI in Docker waarmee ik te maken heb gekregen:
- je hebt opnieuw een Docker-image nodig voor de bouw. Je moet het image zoeken of je eigen Dockerfile schrijven.
- 90% kans dat je enige SSH-sleutels, gevoelige gegevens moet doorgeven die je liever niet in het Docker-image schrijft.
- de container wordt aangemaakt en gaat weer dood, waardoor alle caches verloren gaan. De volgende bouw zal alle projectafhankelijkheden opnieuw moeten downloaden, en dat is lang en inefficiënt, terwijl tijd geld is.
Ontwikkelaars bouwen geen projecten in Docker-containers (ik was ooit zo'n fan, echt waar, ik heb medelijden met mezelf uit het verleden xD). In Java is er de mogelijkheid om meerdere versies te hebben en met één commando over te schakelen naar degene die nu nodig is. Hetzelfde geldt voor Node.js, er is nvm.
Uitslag
Ik beschouw Docker als een zeer krachtige en flexibele tool, maar dat is ook zijn nadeel (dat klinkt raar, ja). Hiermee raken bedrijven gemakkelijk 'verslaafd', gebruiken het waar nodig en waar niet. Ontwikkelaars starten hun eigen containers, hun eigen omgeving, en dit vloeit vervolgens soepel over naar CI en productie. Het DevOps-team schrijft allerlei fietsen om deze containers te draaien.
Gebruik Docker alleen op het allerlaatste stadium van je werkproces, trek het niet in het project aan het begin. Het lost je zakelijke problemen niet op. Het verschuift de problemen alleen naar een ANDER niveau en biedt zijn eigen oplossingen aan, waardoor je dubbele arbeid verricht.
Wanneer is Docker nodig: ik ben tot de conclusie gekomen dat Docker heel goed is in het optimaliseren van een vastgestelde proces, maar niet in het bouwen van basisfunctionaliteit.
Als je toch hebt besloten Docker te gebruiken, dan:
- wees uiterst voorzichtig
- dwing het gebruik van Docker niet op aan ontwikkelaars
- lokaliseer het gebruik op één plek, verdeel het niet over alle repositories met Dockerfile en docker-compose
PS:
- Onlangs stuitte ik op En ze zeggen dat het heel goed samenwerkt met Ansible en het mogelijk maakt om het proces van het bouwen van beelden (inclusief docker image) te uniformiseren.
Bedankt voor het lezen! Ik wens je transparante oplossingen in je zaken en productieve werkdagen!
Bron: habr.com
