{"id":55161,"date":"2023-09-10T16:40:10","date_gmt":"2023-09-10T14:40:10","guid":{"rendered":"https:\/\/kinsta.com\/nl\/?p=55161&#038;preview=true&#038;preview_id=55161"},"modified":"2023-09-12T09:34:45","modified_gmt":"2023-09-12T07:34:45","slug":"kinsta-docker","status":"publish","type":"post","link":"https:\/\/kinsta.com\/nl\/blog\/kinsta-docker\/","title":{"rendered":"Zo verbeterde Kinsta de end-to-end ontwikkelervaring door elke stap van de productiecyclus te Dockeriseren"},"content":{"rendered":"<p>Bij Kinsta hebben we projecten van alle groottes voor Applicatie Hosting, Database Hosting en Managed WordPress Hosting.<\/p>\n<p>Met de cloudhostingoplossingen van Kinsta kun je <a href=\"https:\/\/sevalla.com\/application-hosting\/\">applicaties deployen<\/a> in een groot aantal talen en frameworks, zoals NodeJS, PHP, Ruby, Go, Scala en Python. Elke applicatie kun je deployen met een Dockerfile. Je kunt je Git repository (gehost op GitHub, GitLab of Bitbucket) koppelen om je code direct op Kinsta te implementeren.<\/p>\n<p>Je kunt <a href=\"https:\/\/sevalla.com\/database-hosting\/\">MariaDB, Redis, MySQL en PostgreSQL databases<\/a> out-of-the-box hosten, waardoor je tijd overhoudt om je te richten op het ontwikkelen van je applicaties in plaats van je bezig te houden met hosting configuraties.<\/p>\n<p>En als je kiest voor onze <a href=\"https:\/\/kinsta.com\/nl\/wordpress-hosting\/\">Managed WordPress Hosting<\/a>, ervaar je de kracht van Google Cloud C2 machines op hun Premium Tier netwerk en Cloudflare ge\u00efntegreerde beveiliging, waardoor je WordPress websites de snelste en veiligste op de markt zijn.<br \/>\n<div><\/div><kinsta-auto-toc heading=\"Table of Contents\" list-style=\"arrow\" selector=\"h2\" count-number=\"-1\"><\/kinsta-auto-toc><\/p>\n<h2>De uitdaging van het ontwikkelen van cloud-native applicaties binnen een gedistribueerd team overwinnen<\/h2>\n<p>Een van de grootste uitdagingen bij het ontwikkelen en onderhouden van cloud-native applicaties op bedrijfsniveau is een consistente ervaring gedurende de hele levenscyclus van de ontwikkeling. Dit is nog moeilijker voor bedrijven die op afstand werken met remote teams die werken op verschillende platforms, met verschillende setups en asynchrone communicatie. We moeten dus een consistente, betrouwbare en schaalbare oplossing bieden die werkt voor:<\/p>\n<ul>\n<li>Developers en kwaliteitsmonitoringsteams, ongeacht hun besturingssystemen, een eenvoudige en minimale setup cre\u00ebren voor het ontwikkelen en testen van features.<\/li>\n<li>DevOps-, SysOps- en Infra-teams, voor het configureren en onderhouden van test- en productieomgevingen.<\/li>\n<\/ul>\n<p>Bij Kinsta vertrouwen we sterk op <a href=\"https:\/\/kinsta.com\/nl\/blog\/wat-is-docker\/\">Docker<\/a> voor deze consistente ervaring bij elke stap, van ontwikkeling tot productie. In dit bericht leiden we je door:<\/p>\n<ul>\n<li>Hoe je Docker Desktop kunt gebruiken om de productiviteit van developers te verhogen.<\/li>\n<li>Hoe we Docker images bouwen en naar Google Container Registry pushen via CI pipelines met CircleCI en GitHub Actions.<\/li>\n<li>Hoe we CI pipelines gebruiken om incrementele wijzigingen naar productie te promoten met behulp van Docker images, Google Kubernetes Engine en Cloud Deploy.<\/li>\n<li>Hoe het QA team naadloos gebruik maakt van voorgebouwde Docker images in verschillende omgevingen.<\/li>\n<\/ul>\n<h2>Docker Desktop gebruiken om de ervaring voor developers te verbeteren<\/h2>\n<p>Om een applicatie lokaal te runnen, moeten developers de omgeving minutieus voorbereiden, alle dependencies installeren, servers en services instellen en ervoor zorgen dat ze goed geconfigureerd zijn. Als je meerdere applicaties runt, kan dit lastig zijn, vooral als het gaat om complexe projecten met meerdere dependencies. Als je aan deze variabele ook nog eens meerdere medewerkers met meerdere besturingssystemen toevoegt, ontstaat er chaos. Om dit te voorkomen, gebruiken we Docker.<\/p>\n<p>Met Docker kun je de omgevingsconfiguraties aangeven, de dependencies installeren en images bouwen met alles op de plek waar ze horen. Iedereen, waar dan ook, met welk OS dan ook kan dezelfde images gebruiken en precies dezelfde ervaring hebben als ieder ander.<\/p>\n<h2>Je configuratie declaren met Docker Compose<\/h2>\n<p>Om te beginnen maak je een <a href=\"https:\/\/docs.docker.com\/compose\/\" target=\"_blank\" rel=\"noopener noreferrer\">Docker Compose<\/a> bestand, <code>docker-compose.yml<\/code>. Het is een declaratief configuratiebestand geschreven in YAML format dat Docker vertelt wat de gewenste status van je applicatie is. Docker gebruikt deze informatie om de omgeving voor je applicatie in te stellen.<\/p>\n<p>Docker Compose bestanden zijn erg handig als je meer dan \u00e9\u00e9n container hebt draaien en er dependencies zijn die je gebruikt voor meerdere containers.<\/p>\n<p>Om je <code>docker-compose.yml<\/code> bestand te maken:<\/p>\n<ol>\n<li>Begin met het kiezen van een <a href=\"https:\/\/hub.docker.com\/\" target=\"_blank\" rel=\"noopener noreferrer\"><code>image<\/code><\/a> als basis voor onze applicatie. Zoek op Docker Hub en probeer een Docker image te vinden die al de dependencies van je app bevat. Zorg ervoor dat je een specifieke image tag gebruikt om fouten te voorkomen. Het gebruik van de tag <code>latest<\/code> kan onvoorziene fouten in je applicatie veroorzaken. Je kunt meerdere base images gebruiken voor meerdere dependencies. Bijvoorbeeld \u00e9\u00e9n voor <a href=\"https:\/\/kinsta.com\/nl\/blog\/wat-is-postgresql\/\">PostgreSQL<\/a> en \u00e9\u00e9n voor <a href=\"https:\/\/kinsta.com\/nl\/blog\/redis-docker\/\">Redis<\/a>.<\/li>\n<li>Gebruik <a href=\"https:\/\/docs.docker.com\/storage\/volumes\/\" target=\"_blank\" rel=\"noopener noreferrer\"><code>volumes<\/code><\/a> om gegevens op je host te bewaren als dat nodig is. Door gegevens op de hostmachine te bewaren voorkom je dat je gegevens kwijtraakt als docker-containers worden verwijderd of als je ze opnieuw moet maken.<\/li>\n<li>Gebruik <a href=\"https:\/\/docs.docker.com\/network\/\" target=\"_blank\" rel=\"noopener noreferrer\"><code>networks<\/code><\/a> om je opstelling te isoleren om netwerkconflicten met de host en andere containers te voorkomen. Het helpt je containers ook om elkaar gemakkelijk te vinden en met elkaar te communiceren.<\/li>\n<\/ol>\n<p>Als we alles samenbrengen, hebben we een <code>docker-compose.yml<\/code> die er als volgt uitziet:<\/p>\n<pre><code class=\"language-yaml\">version: '3.8'services:\n  db:\n    image: postgres:14.7-alpine3.17\n    hostname: mk_db\n    restart: on-failure\n    ports:\n      - ${DB_PORT:-5432}:5432\n    volumes:\n      - db_data:\/var\/lib\/postgresql\/data\n    environment:\n      POSTGRES_USER: ${DB_USER:-user}\n      POSTGRES_PASSWORD: ${DB_PASSWORD:-password}\n      POSTGRES_DB: ${DB_NAME:-main}\n    networks:\n      - mk_network\n  redis:\n    image: redis:6.2.11-alpine3.17\n    hostname: mk_redis\n    restart: on-failure\n    ports:\n      - ${REDIS_PORT:-6379}:6379\n    networks:\n      - mk_network\n      \nvolumes:\n  db_data:\n\nnetworks:\n  mk_network:\n    name: mk_network<\/code><\/pre>\n<h2>De applicatie containeriseren<\/h2>\n<h3>Een Docker image bouwen voor je applicatie<\/h3>\n<p>Eerst moeten we een Docker image bouwen met behulp van een <code>Dockerfile<\/code>, en die callen vanuit <code>docker-compose.yml<\/code>.<\/p>\n<p>Om je <code>Dockerfile<\/code> bestand te maken:<\/p>\n<ol>\n<li>Begin met het kiezen van een image als basis. Gebruik het kleinste basisimage dat werkt voor de app. Meestal zijn alpine images zeer minimaal en zijn er bijna geen extra pakketten ge\u00efnstalleerd. Je kunt beginnen met een alpine image en daarop verder bouwen:\n<pre><code class=\"language-markdown\">FROM node:18.15.0-alpine3.17\n<\/code><\/pre>\n<\/li>\n<li>Soms moet je een specifieke CPU architectuur gebruiken om conflicten te voorkomen. Stel bijvoorbeeld dat je een <code>arm64-based<\/code> processor gebruikt, maar je moet een <code>amd64<\/code> image bouwen. Je kunt dat doen door de <code>-- platform<\/code> op te geven in <code>Dockerfile<\/code>:\n<pre><code class=\"language-markdown\">FROM --platform=amd64 node:18.15.0-alpine3.17\n<\/code><\/pre>\n<\/li>\n<li>Definieer de applicatiemap en installeer de dependencies en kopieer de uitvoer naar je hoofdmap:\n<pre><code class=\"language-markdown\">WORKDIR \/opt\/app \nCOPY package.json yarn.lock .\/ \nRUN yarn install \nCOPY . .<\/code><\/pre>\n<\/li>\n<li>Call de <code>Dockerfile<\/code> vanaf <code>docker-compose.yml<\/code>:\n<pre><code class=\"language-yaml\">services:\n  ...redis\n  ...db\n  \n  app:\n    build:\n      context: .\n      dockerfile: Dockerfile\n    platforms:\n      - \"linux\/amd64\"\n    command: yarn dev\n    restart: on-failure\n    ports:\n      - ${PORT:-4000}:${PORT:-4000}\n    networks:\n      - mk_network\n    depends_on:\n      - redis\n      - db<\/code><\/pre>\n<\/li>\n<li>Implementeer auto-reload zodat wanneer je iets verandert in de sourcecode, je direct een voorbeeld van je wijzigingen kunt bekijken zonder dat je de applicatie handmatig opnieuw hoeft te bouwen. Om dat te doen, bouw je eerst de image en voer je die uit in een aparte service:\n<pre><code class=\"language-yaml\">services:\n  ... redis\n  ... db\n  \n  build-docker:\n    image: myapp\n    build:\n      context: .\n      dockerfile: Dockerfile\n  app:\n    image: myapp\n    platforms:\n      - \"linux\/amd64\"\n    command: yarn dev\n    restart: on-failure\n    ports:\n      - ${PORT:-4000}:${PORT:-4000}\n    volumes:\n      - .:\/opt\/app\n      - node_modules:\/opt\/app\/node_modules\n    networks:\n      - mk_network\n    depends_on:\n      - redis\n      - db\n      - build-docker\n      \nvolumes:\n  node_modules:<\/code><\/pre>\n<\/li>\n<\/ol>\n<p>Pro Tip: Merk op dat <code>node_modules<\/code> ook expliciet wordt gemount om platform-specifieke problemen met pakketten te voorkomen. Dit betekent dat in plaats van de <code>node_modules<\/code> op de host te gebruiken, de docker container de zijne gebruikt, maar deze op de host in een apart volume mapt.<\/p>\n<h2>Incrementeel de productie-image bouwen met continue integratie<\/h2>\n<p>De meeste van onze apps en diensten gebruiken CI\/CD voor de deployment. Docker speelt een belangrijke rol in het proces. Elke wijziging in de main branch activeert onmiddellijk een bouwpipeline via GitHub Actions of CircleCI. De algemene workflow is heel eenvoudig: het installeert de dependencies, voert de tests uit, bouwt het docker image en pusht het naar Google Container Registry (of Artifact Registry). Het deel dat we in dit artikel bespreken is de bouwstap.<\/p>\n<h3>De Docker images bouwen<\/h3>\n<p>We gebruiken builds in meerdere fasen om veiligheids- en prestatieredenen.<\/p>\n<h4>Fase 1: Builder<\/h4>\n<p>In dit stadium kopi\u00ebren we de hele codebase met alle broncode en configuratie, installeren we alle dependencies, inclusief dev dependencies, en bouwen we de app. Er wordt een map <code>dist\/<\/code> aangemaakt en de gebouwde versie van de code wordt daarheen gekopieerd. Maar dit image is veel te groot met een enorme set footprints om te gebruiken voor productie. Omdat we private NPM registries gebruiken, gebruiken we in deze fase ook onze private <code>NPM_TOKEN<\/code>. We willen dus absoluut niet dat deze stap wordt blootgesteld aan de buitenwereld. Het enige dat we nodig hebben van deze stap is de map <code>dist\/<\/code>.<\/p>\n<h4>Stap 2: Productie<\/h4>\n<p>De meeste mensen gebruiken dit stadium voor runtime, omdat het heel dicht ligt bij wat we nodig hebben om de app te draaien. We moeten echter nog steeds productie-dependencies installeren en dat betekent dat we footprints achterlaten en de <code>NPM_TOKEN<\/code> nodig hebben. Dit stadium is dus nog niet klaar voor gebruik. Let ook op <code>yarn cache clean<\/code> op regel 19. Dat kleine commando vermindert de grootte van onze afbeelding met wel 60%.<\/p>\n<h4>Fase 3: Runtime<\/h4>\n<p>De laatste stap moet zo lean mogelijk zijn met minimale footprints. Dus we kopi\u00ebren simpelweg de app uit productie en gaan verder. We laten alle yarn en <code>NPM_TOKEN<\/code> dingen achter ons en draaien alleen de app.<\/p>\n<p>Dit is de uiteindelijke <code>Dockerfile.production<\/code>:<\/p>\n<pre><code class=\"language-markdown\"># Stage 1: build the source code \nFROM node:18.15.0-alpine3.17 as builder \nWORKDIR \/opt\/app \nCOPY package.json yarn.lock .\/ \nRUN yarn install \nCOPY . . \nRUN yarn build \n\n# Stage 2: copy the built version and build the production dependencies FROM node:18.15.0-alpine3.17 as production \nWORKDIR \/opt\/app \nCOPY package.json yarn.lock .\/ \nRUN yarn install --production && yarn cache clean \nCOPY --from=builder \/opt\/app\/dist\/ .\/dist\/ \n\n# Stage 3: copy the production ready app to runtime \nFROM node:18.15.0-alpine3.17 as runtime \nWORKDIR \/opt\/app \nCOPY --from=production \/opt\/app\/ . \nCMD [\"yarn\", \"start\"]<\/code><\/pre>\n<p>Let op dat we voor alle stappen eerst de bestanden <code>package.json<\/code> en <code>yarn.lock<\/code> kopi\u00ebren, de dependencies installeren en dan de rest van de codebasis kopi\u00ebren. De reden hiervoor is dat Docker elk commando bouwt als een laag bovenop de vorige. En elke build kan de vorige lagen gebruiken als die beschikbaar zijn en alleen de nieuwe lagen bouwen omwille van de prestaties.<\/p>\n<p>Stel dat je iets hebt veranderd in <code>src\/services\/service1.ts<\/code> zonder de pakketten aan te raken. Dat betekent dat de eerste vier lagen van builder fase onaangeroerd zijn en hergebruikt kunnen worden. Dat maakt het bouwproces ongelooflijk veel sneller.<\/p>\n<h3>De app naar Google Container Registry pushen via CircleCI pipelines<\/h3>\n<p>Er zijn verschillende manieren om een Docker image te bouwen in CircleCI pipelines. In ons geval hebben we ervoor gekozen om <code>circleci\/gcp-gcr orbs<\/code> te gebruiken:<\/p>\n<pre><code class=\"language-yaml\">executors:\n  docker-executor:\n    docker:\n      - image: cimg\/base:2023.03\norbs:\n  gcp-gcr: circleci\/gcp-gcr@0.15.1\njobs:\n  ...\n  deploy:\n    description: Build & push image to Google Artifact Registry\n    executor: docker-executor\n    steps:\n      ...\n      - gcp-gcr\/build-image:\n          image: my-app\n          dockerfile: Dockerfile.production\n          tag: ${CIRCLE_SHA1:0:7},latest\n      - gcp-gcr\/push-image:\n          image: my-app\n          tag: ${CIRCLE_SHA1:0:7},latest<\/code><\/pre>\n<p>Dankzij Docker is er een minimale configuratie nodig om onze app te bouwen en te pushen.<\/p>\n<h3>De app naar Google Container Registry pushen via GitHub acties<\/h3>\n<p>Als alternatief voor CircleCI kunnen we GitHub Actions gebruiken om de applicatie continu te deployen. We stellen <code>gcloud<\/code> in en bouwen en pushen de Docker image naar <code>gcr.io<\/code>:<\/p>\n<pre><code class=\"language-yaml\">jobs:\n  setup-build:\n    name: Setup, Build\n    runs-on: ubuntu-latest\n\n    steps:\n    - name: Checkout\n      uses: actions\/checkout@v3\n\n    - name: Get Image Tag\n      run: |\n        echo \"TAG=$(git rev-parse --short HEAD)\" &gt;&gt; $GITHUB_ENV\n\n    - uses: google-github-actions\/setup-gcloud@master\n      with:\n        service_account_key: ${{ secrets.GCP_SA_KEY }}\n        project_id: ${{ secrets.GCP_PROJECT_ID }}\n\n    - run: |-\n        gcloud --quiet auth configure-docker\n\n    - name: Build\n      run: |-\n        docker build \n          --tag \"gcr.io\/${{ secrets.GCP_PROJECT_ID }}\/my-app:$TAG\" \n          --tag \"gcr.io\/${{ secrets.GCP_PROJECT_ID }}\/my-app:latest\" \n          .\n\n    - name: Push\n      run: |-\n        docker push \"gcr.io\/${{ secrets.GCP_PROJECT_ID }}\/my-app:$TAG\"\n        docker push \"gcr.io\/${{ secrets.GCP_PROJECT_ID }}\/my-app:latest\"<\/code><\/pre>\n<p>Bij elke kleine wijziging die naar de main branch wordt gepushed, bouwen en pushen we een nieuwe Docker image naar het register.<\/p>\n<h2>Wijzigingen deployen naar Google Kubernetes Engine met behulp van Google Delivery pipelines<\/h2>\n<p>Het hebben van kant-en-klare Docker images voor elke wijziging maakt het ook gemakkelijker om te deployen naar productie of terug te rollen als er iets mis gaat. We gebruiken Google Kubernetes Engine om onze apps te beheren en te serveren en gebruiken Google Cloud Deploy en Delivery Pipelines voor ons Continuous Deployment proces.<\/p>\n<p>Wanneer de Docker image is gebouwd na elke kleine wijziging (met de CI pipeline hierboven getoond) gaan we nog een stap verder en deployen we de wijziging naar ons dev cluster met behulp van <code>gcloud<\/code>. Laten we eens kijken naar die stap in de CircleCI pipeline:<\/p>\n<pre><code class=\"language-yaml\">- run:\n    name: Create new release\n    command: gcloud deploy releases create release-${CIRCLE_SHA1:0:7} --delivery-pipeline my-del-pipeline --region $REGION --annotations commitId=$CIRCLE_SHA1 --images my-app=gcr.io\/${PROJECT_ID}\/my-app:${CIRCLE_SHA1:0:7}<\/code><\/pre>\n<p>Dit activeert een releaseproces om de wijzigingen uit te rollen in ons dev Kubernetes cluster. Na het testen en het verkrijgen van de goedkeuringen, promoten we de wijziging naar test en vervolgens productie. Dit is allemaal mogelijk omdat we voor elke wijziging een lean ge\u00efsoleerd Docker image hebben dat bijna alles heeft wat het nodig heeft. We hoeven de deployment alleen maar te vertellen welke tag hij moet gebruiken.<\/p>\n<h2>Hoe het Quality Assurance team van dit proces profiteert<\/h2>\n<p>Het QA team heeft meestal een pre-productie cloudversie van de te testen apps nodig. Soms moeten ze echter een vooraf gebouwde app lokaal draaien (met alle dependencies) om een bepaalde feature te testen. In deze gevallen willen of hoeven ze niet al die moeite te doen om het hele project te klonen, npm-pakketten te installeren, de app te bouwen, developersfouten tegen te komen en het hele ontwikkelproces te doorlopen om de app werkend te krijgen. Nu alles al beschikbaar is als Docker image op Google Container Registry, hebben ze alleen nog een service nodig in het Docker compose bestand:<\/p>\n<pre><code class=\"language-yaml\">services:\n  ...redis\n  ...db\n  \n  app:\n    image: gcr.io\/${PROJECT_ID}\/my-app:latest\n    restart: on-failure\n    ports:\n      - ${PORT:-4000}:${PORT:-4000}\n    environment:\n      - NODE_ENV=production\n      - REDIS_URL=redis:\/\/redis:6379\n      - DATABASE_URL=postgresql:\/\/${DB_USER:-user}:${DB_PASSWORD:-password}@db:5432\/main\n    networks:\n      - mk_network\n    depends_on:\n      - redis\n      - db<\/code><\/pre>\n<p>Met deze service kunnen ze de applicatie op hun lokale machines opstarten met Docker containers door deze uit te voeren:<\/p>\n<pre><code class=\"language-shell\">docker compose up<\/code><\/pre>\n<p>Dit is een enorme stap in het vereenvoudigen van testprocessen. Zelfs als QA besluit om een specifieke tag van de app te testen, kunnen ze eenvoudig de image tag op regel 6 wijzigen en het Docker compose commando opnieuw uitvoeren. Zelfs als ze besluiten om verschillende versies van de app tegelijkertijd te vergelijken, kunnen ze dat eenvoudig bereiken met een paar tweaks. Het grootste voordeel is dat ons QA team niet wordt geconfronteerd met de uitdagingen die developers op moeten lossen.<\/p>\n<h2>Voordelen van het gebruik van Docker<\/h2>\n<ul>\n<li><strong>Bijna geen footprints voor dependencies<\/strong>: Als je ooit besluit om de versie van Redis of Postgres te upgraden, kun je simpelweg 1 regel veranderen en de app opnieuw uitvoeren. Je hoeft niets op je systeem te veranderen. Bovendien kun je, als je twee apps hebt die allebei Redis nodig hebben (misschien zelfs met verschillende versies), ze allebei in hun eigen ge\u00efsoleerde omgeving laten draaien zonder conflicten met elkaar.<\/li>\n<li><strong>Meerdere instances van de app<\/strong>: Er zijn veel gevallen waarin we dezelfde app met een ander commando moeten uitvoeren. Zoals het initialiseren van de DB, het uitvoeren van tests, het bekijken van DB veranderingen of het luisteren naar berichten. In elk van deze gevallen, omdat we de gebouwde image al klaar hebben, voegen we gewoon een andere service toe aan het Docker compose bestand met een ander commando, en we zijn klaar.<\/li>\n<li><strong>Eenvoudigere testomgeving<\/strong>: Vaker wel dan niet hoef je alleen maar de app te draaien. Je hebt de code, de pakketten of lokale databaseverbindingen niet nodig. Je wilt alleen zeker weten dat de app goed werkt of je hebt een draaiende instantie nodig als backend service terwijl je aan je eigen project werkt. Dat kan ook het geval zijn voor QA, Pull Request reviewers, of zelfs UX mensen die willen controleren of hun ontwerp goed is ge\u00efmplementeerd. Onze docker setup maakt het voor al deze mensen heel gemakkelijk om aan de slag te gaan zonder al te veel technische problemen.<\/li>\n<\/ul>\n<p><em>Dit artikel is oorspronkelijk gepubliceerd op <a href=\"https:\/\/www.docker.com\/blog\/how-kinsta-improved-the-end-to-end-development-experience-by-dockerizing-every-step-of-the-production-cycle\/\">Docker<\/a>.<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Bij Kinsta hebben we projecten van alle groottes voor Applicatie Hosting, Database Hosting en Managed WordPress Hosting. Met de cloudhostingoplossingen van Kinsta kun je applicaties deployen &#8230;<\/p>\n","protected":false},"author":297,"featured_media":55162,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_kinsta_gated_content":false,"_kinsta_gated_content_redirect":"","footnotes":""},"tags":[],"topic":[835,853],"class_list":["post-55161","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","topic-docker","topic-kinsta-diensten"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v24.6 (Yoast SEO v24.6) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Zo verbeterde Kinsta de end-to-end ontwikkelervaring door elke stap van de productiecyclus te Dockeriseren<\/title>\n<meta name=\"description\" content=\"Krijg een volledig overzicht van hoe Kinsta de end-to-end ontwikkelervaring heeft verbeterd door elke stap van de productiecyclus te dockeriseren.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/kinsta.com\/nl\/blog\/kinsta-docker\/\" \/>\n<meta property=\"og:locale\" content=\"nl_NL\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Zo verbeterde Kinsta de end-to-end ontwikkelervaring door elke stap van de productiecyclus te Dockeriseren\" \/>\n<meta property=\"og:description\" content=\"Krijg een volledig overzicht van hoe Kinsta de end-to-end ontwikkelervaring heeft verbeterd door elke stap van de productiecyclus te dockeriseren.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/kinsta.com\/nl\/blog\/kinsta-docker\/\" \/>\n<meta property=\"og:site_name\" content=\"Kinsta\u00ae\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/Kinsta-Nederland-476213452787823\/\" \/>\n<meta property=\"article:published_time\" content=\"2023-09-10T14:40:10+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-09-12T07:34:45+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/kinsta.com\/nl\/wp-content\/uploads\/sites\/7\/2023\/08\/how-kinsta-improved-the-end-to-end-development-experience-by-dockerizing-every-step-of-the-production-cycle.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1460\" \/>\n\t<meta property=\"og:image:height\" content=\"730\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Amin Choroomi\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:description\" content=\"Krijg een volledig overzicht van hoe Kinsta de end-to-end ontwikkelervaring heeft verbeterd door elke stap van de productiecyclus te dockeriseren.\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/kinsta.com\/nl\/wp-content\/uploads\/sites\/7\/2023\/08\/how-kinsta-improved-the-end-to-end-development-experience-by-dockerizing-every-step-of-the-production-cycle.jpg\" \/>\n<meta name=\"twitter:creator\" content=\"@Kinsta_NL\" \/>\n<meta name=\"twitter:site\" content=\"@Kinsta_NL\" \/>\n<meta name=\"twitter:label1\" content=\"Geschreven door\" \/>\n\t<meta name=\"twitter:data1\" content=\"Amin Choroomi\" \/>\n\t<meta name=\"twitter:label2\" content=\"Geschatte leestijd\" \/>\n\t<meta name=\"twitter:data2\" content=\"13 minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/kinsta.com\/nl\/blog\/kinsta-docker\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/kinsta.com\/nl\/blog\/kinsta-docker\/\"},\"author\":{\"name\":\"Amin Choroomi\",\"@id\":\"https:\/\/kinsta.com\/nl\/#\/schema\/person\/afd8216d3181e47da9f6e804526b0a97\"},\"headline\":\"Zo verbeterde Kinsta de end-to-end ontwikkelervaring door elke stap van de productiecyclus te Dockeriseren\",\"datePublished\":\"2023-09-10T14:40:10+00:00\",\"dateModified\":\"2023-09-12T07:34:45+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/kinsta.com\/nl\/blog\/kinsta-docker\/\"},\"wordCount\":2079,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/kinsta.com\/nl\/#organization\"},\"image\":{\"@id\":\"https:\/\/kinsta.com\/nl\/blog\/kinsta-docker\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/kinsta.com\/nl\/wp-content\/uploads\/sites\/7\/2023\/08\/how-kinsta-improved-the-end-to-end-development-experience-by-dockerizing-every-step-of-the-production-cycle.jpg\",\"inLanguage\":\"nl-NL\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/kinsta.com\/nl\/blog\/kinsta-docker\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/kinsta.com\/nl\/blog\/kinsta-docker\/\",\"url\":\"https:\/\/kinsta.com\/nl\/blog\/kinsta-docker\/\",\"name\":\"Zo verbeterde Kinsta de end-to-end ontwikkelervaring door elke stap van de productiecyclus te Dockeriseren\",\"isPartOf\":{\"@id\":\"https:\/\/kinsta.com\/nl\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/kinsta.com\/nl\/blog\/kinsta-docker\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/kinsta.com\/nl\/blog\/kinsta-docker\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/kinsta.com\/nl\/wp-content\/uploads\/sites\/7\/2023\/08\/how-kinsta-improved-the-end-to-end-development-experience-by-dockerizing-every-step-of-the-production-cycle.jpg\",\"datePublished\":\"2023-09-10T14:40:10+00:00\",\"dateModified\":\"2023-09-12T07:34:45+00:00\",\"description\":\"Krijg een volledig overzicht van hoe Kinsta de end-to-end ontwikkelervaring heeft verbeterd door elke stap van de productiecyclus te dockeriseren.\",\"breadcrumb\":{\"@id\":\"https:\/\/kinsta.com\/nl\/blog\/kinsta-docker\/#breadcrumb\"},\"inLanguage\":\"nl-NL\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/kinsta.com\/nl\/blog\/kinsta-docker\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"nl-NL\",\"@id\":\"https:\/\/kinsta.com\/nl\/blog\/kinsta-docker\/#primaryimage\",\"url\":\"https:\/\/kinsta.com\/nl\/wp-content\/uploads\/sites\/7\/2023\/08\/how-kinsta-improved-the-end-to-end-development-experience-by-dockerizing-every-step-of-the-production-cycle.jpg\",\"contentUrl\":\"https:\/\/kinsta.com\/nl\/wp-content\/uploads\/sites\/7\/2023\/08\/how-kinsta-improved-the-end-to-end-development-experience-by-dockerizing-every-step-of-the-production-cycle.jpg\",\"width\":1460,\"height\":730},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/kinsta.com\/nl\/blog\/kinsta-docker\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/kinsta.com\/nl\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Docker\",\"item\":\"https:\/\/kinsta.com\/nl\/onderwerpen\/docker\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Zo verbeterde Kinsta de end-to-end ontwikkelervaring door elke stap van de productiecyclus te Dockeriseren\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/kinsta.com\/nl\/#website\",\"url\":\"https:\/\/kinsta.com\/nl\/\",\"name\":\"Kinsta\u00ae\",\"description\":\"Snelle, veilige, premium hostingoplossingen\",\"publisher\":{\"@id\":\"https:\/\/kinsta.com\/nl\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/kinsta.com\/nl\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"nl-NL\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/kinsta.com\/nl\/#organization\",\"name\":\"Kinsta\",\"url\":\"https:\/\/kinsta.com\/nl\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"nl-NL\",\"@id\":\"https:\/\/kinsta.com\/nl\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/kinsta.com\/nl\/wp-content\/uploads\/sites\/7\/2023\/12\/kinsta-logo.jpeg\",\"contentUrl\":\"https:\/\/kinsta.com\/nl\/wp-content\/uploads\/sites\/7\/2023\/12\/kinsta-logo.jpeg\",\"width\":500,\"height\":500,\"caption\":\"Kinsta\"},\"image\":{\"@id\":\"https:\/\/kinsta.com\/nl\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/Kinsta-Nederland-476213452787823\/\",\"https:\/\/x.com\/Kinsta_NL\",\"https:\/\/www.instagram.com\/kinstahosting\/\",\"https:\/\/www.linkedin.com\/company\/kinsta\/\",\"https:\/\/www.pinterest.com\/kinstahosting\/\",\"https:\/\/www.youtube.com\/c\/Kinsta\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/kinsta.com\/nl\/#\/schema\/person\/afd8216d3181e47da9f6e804526b0a97\",\"name\":\"Amin Choroomi\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"nl-NL\",\"@id\":\"https:\/\/kinsta.com\/nl\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/f986556230b70b812c88e12d0c4726cf?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/f986556230b70b812c88e12d0c4726cf?s=96&d=mm&r=g\",\"caption\":\"Amin Choroomi\"},\"description\":\"Software developer at Kinsta. Passionate about Docker and Kubernetes, he specializes in application development and DevOps practices.\",\"url\":\"https:\/\/kinsta.com\/nl\/blog\/author\/aminchoroomi\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Zo verbeterde Kinsta de end-to-end ontwikkelervaring door elke stap van de productiecyclus te Dockeriseren","description":"Krijg een volledig overzicht van hoe Kinsta de end-to-end ontwikkelervaring heeft verbeterd door elke stap van de productiecyclus te dockeriseren.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/kinsta.com\/nl\/blog\/kinsta-docker\/","og_locale":"nl_NL","og_type":"article","og_title":"Zo verbeterde Kinsta de end-to-end ontwikkelervaring door elke stap van de productiecyclus te Dockeriseren","og_description":"Krijg een volledig overzicht van hoe Kinsta de end-to-end ontwikkelervaring heeft verbeterd door elke stap van de productiecyclus te dockeriseren.","og_url":"https:\/\/kinsta.com\/nl\/blog\/kinsta-docker\/","og_site_name":"Kinsta\u00ae","article_publisher":"https:\/\/www.facebook.com\/Kinsta-Nederland-476213452787823\/","article_published_time":"2023-09-10T14:40:10+00:00","article_modified_time":"2023-09-12T07:34:45+00:00","og_image":[{"width":1460,"height":730,"url":"https:\/\/kinsta.com\/nl\/wp-content\/uploads\/sites\/7\/2023\/08\/how-kinsta-improved-the-end-to-end-development-experience-by-dockerizing-every-step-of-the-production-cycle.jpg","type":"image\/jpeg"}],"author":"Amin Choroomi","twitter_card":"summary_large_image","twitter_description":"Krijg een volledig overzicht van hoe Kinsta de end-to-end ontwikkelervaring heeft verbeterd door elke stap van de productiecyclus te dockeriseren.","twitter_image":"https:\/\/kinsta.com\/nl\/wp-content\/uploads\/sites\/7\/2023\/08\/how-kinsta-improved-the-end-to-end-development-experience-by-dockerizing-every-step-of-the-production-cycle.jpg","twitter_creator":"@Kinsta_NL","twitter_site":"@Kinsta_NL","twitter_misc":{"Geschreven door":"Amin Choroomi","Geschatte leestijd":"13 minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/kinsta.com\/nl\/blog\/kinsta-docker\/#article","isPartOf":{"@id":"https:\/\/kinsta.com\/nl\/blog\/kinsta-docker\/"},"author":{"name":"Amin Choroomi","@id":"https:\/\/kinsta.com\/nl\/#\/schema\/person\/afd8216d3181e47da9f6e804526b0a97"},"headline":"Zo verbeterde Kinsta de end-to-end ontwikkelervaring door elke stap van de productiecyclus te Dockeriseren","datePublished":"2023-09-10T14:40:10+00:00","dateModified":"2023-09-12T07:34:45+00:00","mainEntityOfPage":{"@id":"https:\/\/kinsta.com\/nl\/blog\/kinsta-docker\/"},"wordCount":2079,"commentCount":0,"publisher":{"@id":"https:\/\/kinsta.com\/nl\/#organization"},"image":{"@id":"https:\/\/kinsta.com\/nl\/blog\/kinsta-docker\/#primaryimage"},"thumbnailUrl":"https:\/\/kinsta.com\/nl\/wp-content\/uploads\/sites\/7\/2023\/08\/how-kinsta-improved-the-end-to-end-development-experience-by-dockerizing-every-step-of-the-production-cycle.jpg","inLanguage":"nl-NL","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/kinsta.com\/nl\/blog\/kinsta-docker\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/kinsta.com\/nl\/blog\/kinsta-docker\/","url":"https:\/\/kinsta.com\/nl\/blog\/kinsta-docker\/","name":"Zo verbeterde Kinsta de end-to-end ontwikkelervaring door elke stap van de productiecyclus te Dockeriseren","isPartOf":{"@id":"https:\/\/kinsta.com\/nl\/#website"},"primaryImageOfPage":{"@id":"https:\/\/kinsta.com\/nl\/blog\/kinsta-docker\/#primaryimage"},"image":{"@id":"https:\/\/kinsta.com\/nl\/blog\/kinsta-docker\/#primaryimage"},"thumbnailUrl":"https:\/\/kinsta.com\/nl\/wp-content\/uploads\/sites\/7\/2023\/08\/how-kinsta-improved-the-end-to-end-development-experience-by-dockerizing-every-step-of-the-production-cycle.jpg","datePublished":"2023-09-10T14:40:10+00:00","dateModified":"2023-09-12T07:34:45+00:00","description":"Krijg een volledig overzicht van hoe Kinsta de end-to-end ontwikkelervaring heeft verbeterd door elke stap van de productiecyclus te dockeriseren.","breadcrumb":{"@id":"https:\/\/kinsta.com\/nl\/blog\/kinsta-docker\/#breadcrumb"},"inLanguage":"nl-NL","potentialAction":[{"@type":"ReadAction","target":["https:\/\/kinsta.com\/nl\/blog\/kinsta-docker\/"]}]},{"@type":"ImageObject","inLanguage":"nl-NL","@id":"https:\/\/kinsta.com\/nl\/blog\/kinsta-docker\/#primaryimage","url":"https:\/\/kinsta.com\/nl\/wp-content\/uploads\/sites\/7\/2023\/08\/how-kinsta-improved-the-end-to-end-development-experience-by-dockerizing-every-step-of-the-production-cycle.jpg","contentUrl":"https:\/\/kinsta.com\/nl\/wp-content\/uploads\/sites\/7\/2023\/08\/how-kinsta-improved-the-end-to-end-development-experience-by-dockerizing-every-step-of-the-production-cycle.jpg","width":1460,"height":730},{"@type":"BreadcrumbList","@id":"https:\/\/kinsta.com\/nl\/blog\/kinsta-docker\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/kinsta.com\/nl\/"},{"@type":"ListItem","position":2,"name":"Docker","item":"https:\/\/kinsta.com\/nl\/onderwerpen\/docker\/"},{"@type":"ListItem","position":3,"name":"Zo verbeterde Kinsta de end-to-end ontwikkelervaring door elke stap van de productiecyclus te Dockeriseren"}]},{"@type":"WebSite","@id":"https:\/\/kinsta.com\/nl\/#website","url":"https:\/\/kinsta.com\/nl\/","name":"Kinsta\u00ae","description":"Snelle, veilige, premium hostingoplossingen","publisher":{"@id":"https:\/\/kinsta.com\/nl\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/kinsta.com\/nl\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"nl-NL"},{"@type":"Organization","@id":"https:\/\/kinsta.com\/nl\/#organization","name":"Kinsta","url":"https:\/\/kinsta.com\/nl\/","logo":{"@type":"ImageObject","inLanguage":"nl-NL","@id":"https:\/\/kinsta.com\/nl\/#\/schema\/logo\/image\/","url":"https:\/\/kinsta.com\/nl\/wp-content\/uploads\/sites\/7\/2023\/12\/kinsta-logo.jpeg","contentUrl":"https:\/\/kinsta.com\/nl\/wp-content\/uploads\/sites\/7\/2023\/12\/kinsta-logo.jpeg","width":500,"height":500,"caption":"Kinsta"},"image":{"@id":"https:\/\/kinsta.com\/nl\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/Kinsta-Nederland-476213452787823\/","https:\/\/x.com\/Kinsta_NL","https:\/\/www.instagram.com\/kinstahosting\/","https:\/\/www.linkedin.com\/company\/kinsta\/","https:\/\/www.pinterest.com\/kinstahosting\/","https:\/\/www.youtube.com\/c\/Kinsta"]},{"@type":"Person","@id":"https:\/\/kinsta.com\/nl\/#\/schema\/person\/afd8216d3181e47da9f6e804526b0a97","name":"Amin Choroomi","image":{"@type":"ImageObject","inLanguage":"nl-NL","@id":"https:\/\/kinsta.com\/nl\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/f986556230b70b812c88e12d0c4726cf?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/f986556230b70b812c88e12d0c4726cf?s=96&d=mm&r=g","caption":"Amin Choroomi"},"description":"Software developer at Kinsta. Passionate about Docker and Kubernetes, he specializes in application development and DevOps practices.","url":"https:\/\/kinsta.com\/nl\/blog\/author\/aminchoroomi\/"}]}},"acf":[],"_links":{"self":[{"href":"https:\/\/kinsta.com\/nl\/wp-json\/wp\/v2\/posts\/55161","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/kinsta.com\/nl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kinsta.com\/nl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kinsta.com\/nl\/wp-json\/wp\/v2\/users\/297"}],"replies":[{"embeddable":true,"href":"https:\/\/kinsta.com\/nl\/wp-json\/wp\/v2\/comments?post=55161"}],"version-history":[{"count":4,"href":"https:\/\/kinsta.com\/nl\/wp-json\/wp\/v2\/posts\/55161\/revisions"}],"predecessor-version":[{"id":55401,"href":"https:\/\/kinsta.com\/nl\/wp-json\/wp\/v2\/posts\/55161\/revisions\/55401"}],"alternate":[{"embeddable":true,"hreflang":"en","title":"English","href":"https:\/\/kinsta.com\/nl\/wp-json\/kinsta\/v1\/posts\/55161\/translations\/en"},{"embeddable":true,"hreflang":"it","title":"Italian","href":"https:\/\/kinsta.com\/nl\/wp-json\/kinsta\/v1\/posts\/55161\/translations\/it"},{"embeddable":true,"hreflang":"pt","title":"Portuguese","href":"https:\/\/kinsta.com\/nl\/wp-json\/kinsta\/v1\/posts\/55161\/translations\/pt"},{"embeddable":true,"hreflang":"fr","title":"French","href":"https:\/\/kinsta.com\/nl\/wp-json\/kinsta\/v1\/posts\/55161\/translations\/fr"},{"embeddable":true,"hreflang":"de","title":"German","href":"https:\/\/kinsta.com\/nl\/wp-json\/kinsta\/v1\/posts\/55161\/translations\/de"},{"embeddable":true,"hreflang":"ja","title":"Japanese","href":"https:\/\/kinsta.com\/nl\/wp-json\/kinsta\/v1\/posts\/55161\/translations\/jp"},{"embeddable":true,"hreflang":"nl","title":"Dutch","href":"https:\/\/kinsta.com\/nl\/wp-json\/kinsta\/v1\/posts\/55161\/translations\/nl"},{"embeddable":true,"hreflang":"es","title":"Spanish","href":"https:\/\/kinsta.com\/nl\/wp-json\/kinsta\/v1\/posts\/55161\/translations\/es"},{"href":"https:\/\/kinsta.com\/nl\/wp-json\/kinsta\/v1\/posts\/55161\/tree"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/kinsta.com\/nl\/wp-json\/wp\/v2\/media\/55162"}],"wp:attachment":[{"href":"https:\/\/kinsta.com\/nl\/wp-json\/wp\/v2\/media?parent=55161"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kinsta.com\/nl\/wp-json\/wp\/v2\/tags?post=55161"},{"taxonomy":"topic","embeddable":true,"href":"https:\/\/kinsta.com\/nl\/wp-json\/wp\/v2\/topic?post=55161"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}