As web applications become more complex, software engineering teams must rely on many different products and services to create the best developer experience. The application development ecosystem has grown beyond version control and hosting deployment. Manually managing the deployment of new features across all services can create a serious bottleneck in the software development lifecycle. It also introduces the risk of human error.

In this article, I will describe how to deploy a Dockerized Laravel application to Microsoft Azure using GitHub for version control via CircleCI. You will take a previously-built Laravel API project, build a container image out of it, and then push the image to the Azure container registry. Then, you will learn how to create an Azure web service as an application and connect the container image to it.

Microsoft Azure Web Apps is a platform as a service (PaaS) that lets you publish Web apps running on multiple frameworks, written in different programming languages. You can then use a CI/CD tool to build, test, and deploy web applications for a faster release cycle, more efficient development, and higher-quality code.


In addition to a basic understanding of Laravel and PHP, you will need the following items to get the most from this tutorial:

  • Docker Desktop installed on your local machine. You can follow Docker’s tutorial for Windows or macOS.
  • A GitHub account.
  • A CircleCI account.
  • An Azure account.

Our tutorials are platform-agnostic, but use CircleCI as an example. If you don’t have a CircleCI account, sign up for a free one here.

Cloning the demo project

Clone the sample Laravel project by running this command:

git clone

Next, go to the root of the new folder you just created. Set up the project by running these commands:

cd laravel-azure-api

composer install 

cp .env.example .env
php artisan key:generate

php artisan serve

These commands will change directory into the laravel-azure-api project from the terminal and:

  • Install all the project’s dependencies
  • Create a .env file and copy the content of .env.example file into it
  • Generate an application key
  • Run the application

By default, your application will be served to Go to this endpoint to view the json response.

View application locally

You can use this command to run the unit tests:

php vendor/bin/phpunit

Reviewing the deployment strategy

Now that you have the application running locally, it is a good time to review your deployment strategy. There is no need for any project code changes other than including the configuration file to set up deployment for CircleCI.

In chronological order, you will need to:

  1. Create a registry to host your container image on Azure container registry (ACR) and obtain the access key. ACR is a private registry owned by Microsoft for hosting Docker images.
  2. Create a container image for the project, build, and then run the container locally.
  3. Publish the Docker image to the Azure container registry.
  4. Create an Azure web app and link it with the published container image.
  5. Enable continuous deployment and create a configuration file to build and deploy the container image on CircleCI.
  6. Push the project to GitHub and connect with CircleCI.
  7. Deploy the container image to the Azure container registry.

Creating an Azure Container Registry

If you do not have one already, create an account on Azure. Go to the Azure portal dashboard and click Create a resource.

Create Resource

Select Containers > Container Registry to create a new registry.

Create registry

On the registry creation page, input the required details.

Create container registry

Note: You can create a new resource group for this project or use an existing one.

Click Review + Create. You will be redirected to a page where you can review the registry information. Click Create to set up a new registry instance.

Obtaining an access key from the registry

In this section, you will enable Docker access in the Azure container registry. This step is crucial to the deployment process. Enabling Docker access lets you log into the Azure container registry remotely through the CLI and push images to it.

Open the registry and locate the Access Keys link under the Settings section.

This will show you the registry name and login server. Use the toggle button to enable the admin user. Then, copy the username and any of the passwords, preferably the first one. Keep this somewhere handy; you will be need it later on in the tutorial.

Enable admin

Containerizing the application locally

Your next step is writing a custom Docker file that will allow you to build a container image. From the root of the application, create a new file named Dockerfile. Open the file and paste this content into it:

FROM php:8.0.20

RUN curl -sS | php -- \
     --install-dir=/usr/local/bin --filename=composer

COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

RUN apt-get update && apt-get install -y zlib1g-dev \
    libzip-dev \

RUN docker-php-ext-install pdo pdo_mysql sockets zip

RUN mkdir /app

ADD . /app


RUN composer install

CMD php artisan serve --host= --port=8000


PHP version 8 is used as the base image. The subsequent commands install composer, the extensions for a Laravel application, and enable the PHP PDO and MySQL extensions.

When the installation is complete, set the working directory to app and copy the files from your local machine into the working directory of the container. Then run composer install and include the command to run the application.

Building the Docker image

Run the command below to build a Docker image for the project:

docker build -t .

This command will look in the project for the Dockerfile and build the container image based on the contained instructions. Notice that the command above uses the registry name and login server from the registry created earlier? The benefit of this approach is to easily map the container image with the Azure container registry.

Docker build output

Running the Docker image

Now that we have successfully built the local version of the container image, run it with this command to ensure that it works:

docker run -d -p 8000:8000

This will run the app on port 800. Verify it by visiting http://localhost:8000.

Pushing the Docker image to Azure Registry

Next, log into the Azure container registry created earlier and push the container image to it. Issue this command from the terminal:

docker login -u DOCKER_USER -p DOCKER_PASS

Replace these placeholders with your values:

  • DOCKER_USER: The username obtained for the container registry.
  • DOCKER_PASS: The password from the container registry.

After you log in, use this command to push the image to the Azure registry:

docker push

View repository

Creating an Azure web app for the container

Next, you need to create an Azure Web App and connect it with the container image. Go to the Azure portal homepage and click Create a resource.

Select Containers > Web App for Containers to create a new web app service instance.

Create Web app for container

You will be redirected to the Create Web App page. Select an Azure subscription and a resource group. Create a new resource group if you need to. Docker container should be selected by default, if it is no, click to select it.

Create web app

From the Docker tab, select the image source and its respective Docker image.

Select Docker image

When you click Review + Create, you will be redirected to a page where you can review the web app details. Click Create to set up a new Azure web app.

When the process is completed, you can visit the URL, to review the app as deployed to Azure.

Laravel app live

Enable continuous deployment

Each time your Docker image is updated, you want the app will receive the update. To do this, you need to enable continuous deployment for the web app service.

Click on the web app name, then click Deployment Center. On the Settings tab, scroll to the Continuous Deployment button and click to select it. Click Save to persist the changes.

Enable continuous deployment

With continuous deployment selected, the web app will trigger a new deployment of the Laravel application each time the Docker image is rebuilt on Azure Container Registry.

Automating the deployment

In this step, you will add the pipeline configuration for CircleCI. This pipeline automates testing and runs the commands that build and push the container image to the Azure container registry.

At the root of your project, open the .circleci/config.yml file. Update its content as shown here:

version: 2.1
  docker: circleci/docker@2.1.2
    description: Setup laravel application and run tests
      # Specify the version you desire here
      - image: cimg/php:8.0-browsers

      - checkout

      - run:
          name: "Prepare environment"
          command: |
            sudo apt update
      # Download and cache dependencies
      - restore_cache:
            # "composer.lock" can be used if it is committed to the repo
            - v1-dependencies-{{ checksum "composer.json" }}
            # fallback to using the latest cache if no exact match is found
            - v1-dependencies-

      - run:
          name: "Install dependencies"
          command: composer install -n --prefer-dist

      - save_cache:
          key: v1-dependencies-{{ checksum "composer.json" }}
            - ./vendor

      - run:
          name: "Create .env file and generate app key"
          command: |
            mv .env.example .env
            php artisan key:generate

      - run:
          name: "Run tests"
          command: php vendor/bin/phpunit

      name: docker/docker
      tag: "3.6"
      - checkout
      - docker/install-docker-tools
      - setup_remote_docker:
          version: 20.10.14
          docker_layer_caching: true
      - run:
          name: "Build and push Docker image"
          command: |
            docker build -t .
            docker login -u $DOCKER_USER -p $DOCKER_PASS
            docker push

      - build-and-test
      - build-docker-image:
            - build-and-test

Here is a breakdown of the configuration.

The CircleCI configuration always starts with the version. For this tutorial, we are using version 2.1.

The next part of the configuration specifies two different jobs:

  • build-and-test
  • build-docker-image

The build-and-test job uses the CircleCI PHP 8 Docker image, checks out our project from GitHub, installs the project’s dependencies, sets up the environment variables, and runs the application’s tests.

The build-docker-image job creates a Docker image for the code pulled from the Github repository and updates the Azure container registry with the latest version of the container. The requires key specifies that the build-docker-image does not run until the build job is complete.

Connecting the application to CircleCI

Now you need to set up a repository on GitHub and link the project to CircleCI. Review Pushing a project to GitHub for instructions.

Log into your CircleCI account. If you signed up with your GitHub account, all your repositories will be available on your project’s dashboard.

Click Set Up Project next to your laravel-azure-api project.

Select project

You will be prompted to either write a new configuration file or use the existing one in your project. Select the existing one and enter the name of the branch where your code is housed on GitHub. Click Let’s Go.

Select configuration file

Your first workflow will start running.

The build-docker-image job will fail because you have not yet provided your Azure container registry credentials.

To fix that, you will need to add username and password environment variables. Click Project Settings.

Click Environment Variables. Create these variables:

  • The DOCKER_USERNAME variable is the username obtained for the container registry.
  • The DOCKER_PASS variable is the password from the container registry.

Go back to the dashboard. Click Rerun Workflow from Start.

This time, your workflow will run successfully. Now you can make changes to the codebase locally and push it to GitHub using continuous deployment.


And there you have it. Using Docker, CircleCI, and Microsoft Azure you were able to automate the deployment process of a Laravel application. You performed the setup process to ensure that, each time you update the project and push the changes to GitHub, CircleCI will use the configuration details to build a new container image and update the associated Azure container registry. And with continuous deployment enabled on the Azure web app, a webhook resource will be fired to push a new version of the container image to the web app.

I hope that you found this tutorial helpful. Check here for the complete source code of the project you built.

Oluyemi is a tech enthusiast with a background in Telecommunication Engineering. With a keen interest in solving day-to-day problems encountered by users, he ventured into programming and has since directed his problem solving skills at building software for both web and mobile. A full stack software engineer with a passion for sharing knowledge, Oluyemi has published a good number of technical articles and blog posts on several blogs around the world. Being tech savvy, his hobbies include trying out new programming languages and frameworks.

Read more posts by Olususi Oluyemi