How can I use DinD inside an image that I'm building?

I am currently building a docker image on top of php8.0-fpm where I am adding composer, sentry-cli etc… and then using this image in future jobs to test and deploy my application. However, in the latest version of Laravel Vapor, it is recommended that you dockerize your application before deploying it. The issue is that the php8.0-fpm that I am using doesn’t have docker installed. I will add both my Dockerfile and gitlab-ci script below for further context.

I would appreciate any help possible! Thank you.

gitlab-ci.yml

stages:
  - build
  - test
  - deploy

cache:
    paths:
        - vendor/

variables:
  DOCKER_TLS_CERTDIR: ""
  DOCKER_DRIVER: overlay2
  DOCKER_HOST: tcp://docker:2375

build:
  image: docker:latest
  stage: build
  services:
    - docker:dind
  script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
    - docker pull $CI_REGISTRY_IMAGE:latest || true
    - docker build --cache-from $CI_REGISTRY_IMAGE:latest --tag $CI_REGISTRY_IMAGE:latest .
    - docker push $CI_REGISTRY_IMAGE:latest

test:
  image: $CI_REGISTRY_IMAGE:latest
  stage: test
  services:
    - docker:dind
  artifacts:
        paths:
          - vendor/
  script:
    - composer install
    - touch database/database.sqlite
    - php artisan key:generate --env=testing
    - php artisan migrate --env=testing
    - php artisan passport:install --env=testing
    - php artisan db:seed --env=testing
    - php artisan geoip:update --env=testing
    - php artisan test --env=testing

deploy_development:
  image: $CI_REGISTRY_IMAGE:latest
  stage: deploy
  services:
    - docker:dind
  artifacts:
        paths:
          - vendor/
  environment:
    name: development
    url: https://dev.xxx.io
  script:
    - VERSION=$(sentry-cli releases propose-version)
    - sentry-cli releases new -p api $VERSION
    - sentry-cli releases set-commits --auto $VERSION
    - composer install
    - php vendor/bin/vapor deploy development --commit="$CI_COMMIT_SHA"
  only:
    - development

deploy_staging:
  image: $CI_REGISTRY_IMAGE:latest
  stage: deploy
  services:
    - docker:dind
  artifacts:
        paths:
          - vendor/
  environment:
    name: staging
    url: https://stage.xxx.io
  script:
    - VERSION=$(sentry-cli releases propose-version)
    - sentry-cli releases new -p api $VERSION
    - sentry-cli releases set-commits --auto $VERSION
    - composer install
    - php vendor/bin/vapor deploy staging --commit="$CI_COMMIT_SHA"
  only:
    - master

deploy_production:
  image: $CI_REGISTRY_IMAGE:latest
  stage: deploy
  services:
    - docker:dind
  artifacts:
        paths:
          - vendor/
  when: manual
  environment:
    name: production
    url: https://xxx.io
  script:
    - VERSION=$(sentry-cli releases propose-version)
    - sentry-cli releases new -p api $VERSION
    - sentry-cli releases set-commits --auto $VERSION
    - sentry-cli releases finalize "$VERSION"
    - composer install
    - php vendor/bin/vapor deploy production --commit="$CI_COMMIT_SHA"
  only:
    - master

Dockerfile

    FROM php:8.0-fpm as builder

    # Require composer dependency manager
    COPY --from=composer /usr/bin/composer /usr/bin/composer

    # Require install-php-extensions script (https://github.com/mlocati/docker-php-extension-installer)
    COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/

    # Update apt repository
    RUN apt-get update -y

    # Install requirements
    RUN apt-get install -y libgmp-dev re2c libmhash-dev libmcrypt-dev file libzip-dev zlib1g-dev libicu-dev g++
    RUN ln -s /usr/include/x86_64-linux-gnu/gmp.h /usr/local/include/
    RUN docker-php-ext-configure gmp
    RUN docker-php-ext-configure intl

    # Install php extensions
    RUN docker-php-ext-install gmp intl zip pdo

    # Install php extensions (via 3rd party script)
    RUN install-php-extensions http

    # Install Sentry-CLI
    RUN curl -sL https://sentry.io/get-cli/ | bash

Hi @KieronWiltshire
You don’t want to use DinD inside an image. You build the image using DinD :slight_smile:
You are already building container image so it should be easy to built it on top. Looking at this blog you need to do some changes to Vapor setup and provide a .Dockerfile for Vapor to build it. Now I suppose here that it can take any image you provide and not just official laravelphp/vapor images.

You don’t need to have services: - docker:dind in every job. Only in the ones you are using it.
I would also use cache: for vendor/ instead of artifacts. Unless you need it to be downloadable from GitLab.

I usually keep the php-fpm base image in a separate repository so it doesn’t get build every time I change something in the code. And to more easily identify if it’s broken by code change or some dependency/requirement got updated and broke it :slight_smile: But let’s make it in a single repo for now.

So you have the container image you are using for test job. You need to add Dockerfile per environment like development.Dockerfile file to your repository and update the deploy_* jobs script steps.
development.Dockerfile should be fairly simple, just copy everything to the image. I don’t recommend running apps as root user. Adjust accordingly.

FROM _path_to_your_fpm_base_image_:latest

# Add user for laravel application
RUN groupadd -g 1000 www &&\
    useradd -u 1000 -ms /bin/bash -g www www

# Copy existing application directory permissions
COPY --chown=www:www . /var/www

# Set working directory
WORKDIR /var/www

# Change current user to www
USER www

Add another step (before vapor deploy) to your script: in your deploy_* jobs and install docker into your php-fpm image (it is Debian based). Looking at VaporCLI code it just calls docker command on shell.

1 Like

Yeah the problem is I can’t install the composer dependencies from the Vapor image I’m sure… I would have to check but I don’t believe that will solve my problem, or it will cause issues in other steps that will be just as troublesome to solve.

Anyways, I’ll give it a shot and post an update here. Thanks for your help.