---
title: Local Development with DDev
date: 2020-02-11T08:17:00-05:00
author: cc_admin
canonical_url: "https://caffeinecreations.ca/blog/local-development-with-ddev/"
section: Blog
---
![Ddev seo](https://caffeinecreations.ca/uploads/blog/_1920x660_crop_center-center_none_ns/ddev-seo.jpg)

- [Web Development](https://caffeinecreations.ca/blog/category/web-development/), [CraftCMS](https://caffeinecreations.ca/blog/category/craftcms/)

# Local Development with DDev

A discusssion on using DDev for local development as a replacement for Mamp Pro or Xampps.

Local development is key when working on client sites. Over the years I've tried a number of different approaches including cowboy coding live on the server (not recommended), [Xampp](https://www.apachefriends.org/index.html), [Ampps](https://www.ampps.com/), and [Mamp Pro](https://www.mamp.info/en/) for Windows.

I've also looked into [Laravel Valet](https://github.com/laravel/valet) and [Docker](https://www.docker.com/). Valet is most appealing to me but the Windows fork never worked, and then yesterday I tried the fork that required Windows Subsystem for Linux and also had issues with it so moved on.

I additionally spent time [learning Docker](https://www.udemy.com/course/docker-mastery/learn/lecture/6775722#overview) via an excellent course on Udemy, but decided it was too complex and would take too long to figure everything out. I need something that is not difficult and just works and is flexible allowing for different versions of PHP and mysql per site.

![MAMP PRO Logo](https://caffeinecreations.ca/uploads/blog/_400xAUTO_fit_center-center_none_ns/MAMP-PRO-Logo1.jpg)

**Why move on from Mamp Pro?** A couple of reasons, I'm in a situation where I cannot upgrade Mamp Pro to the latest version. This is due to needing php 5.4, 5.5, and 5.6 for older projects and the latest Mamp doesn't include that. Also whenI did upgrade I needed to roll back due to problems with the mysql 5.6 to 5.7 update.

Additionally the max version of PHP available on my version of Mamp Pro is 7.2.1. I tried manually added in php 7.3.14 but couldn't get all the extensions needed for Craft sites to work.

### DDev to the rescue

Once again I was googling and found [DDev](https://www.ddev.com/) which is like a simplified Docker for local development. There is no GUI available but I'm comfortable working on the command line so that's not a big deal.

Part way through getting set up I was stuck and googled once again looking for specific help with Craft and DDev and came across this excellent article by Matt Stein [Mamp Pro to DDEV](https://workingconcept.com/blog/mamp-pro-to-ddev).

At this point I recommend following Matt's instructions and you'll be set up and running. However note that here:

> *Edit 12/9:* Note that there’s no `DB_PORT` specified here. DDEV chooses a new MySQL port every time your project spins up, so we need to let it expose its own `DB_PORT` environment variable (as it does by default).
> 
> 
> 
> ##### Matt Stein

This can be overridden in your in your config.yaml file, by adding this line `host_db_port: "32800"` allowing you to use the same port every time you start the site. Very helpful for saving your settings in Navicat to connect to the database.

#### Matt Saves The Day

Using Matt's article I had this working 99%. However the Craft site that I was working on insisted that craft was not installed despite connecting to the database. on the Craft Discord Server I hit up Matt and he, graciously, spent a few minutes helping me troubleshoot.

My issue was that I had my environment variables in both the dotenv file and the new `docker-compose.environment.yaml` file.This resulted in some conflict and as soon as I commented out all the variables except for `SECURITY_KEY` the site worked.

Now my .env file only has this `SECURITY_KEY="some-random-string-here"` and all of my other dontenv variables are stored in a file located in the .ddev directory called `docker-compose.environment.yaml`. See example below.

```
<button class="absolute z-10 flex items-center justify-center w-8 h-8 -translate-y-1/2  -right-4 -top-4" clipboard="" title="Copy to Clipboard" to="" type="button" x-clipboard.raw="version: '3.6'

services:
  web:
    environment:
      - ENVIRONMENT=dev
      - SECURITY_KEY=random-string-here
      - DB_DRIVER=mysql
      - DB_SERVER=db
      - DB_USER=db
      - DB_PASSWORD=db
      - DB_DATABASE=db
      - DB_PORT=3306
      - DB_SCHEMA=public
      - DB_TABLE_PREFIX=craft_
      - DEFAULT_SITE_URL=https://mysite.ddev.site

      # uploads path
      - ASSET_BASE_PATH=/var/www/html/public/uploads
      - ASSET_BASE_URL=https://mysite.ddev.site/uploads

      #Environment Label
      - CRAFT_ENV_LABEL_PREFIX= Local Site
      - CRAFT_ENV_LABEL_COLOR=#FFFF00
      - CRAFT_ENV_LABEL_TEXT_COLOR=#FF0000

      # site path
      - SITE_PATH=/var/www/html/siteroot" x-data="">
	<svg class="h-5 w-5" viewbox="0 0 64 64" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
  <rect fill="#f3f4f6" height="53" rx="3" width="41" x="7" y="2"></rect>
  <rect fill="#f3f4f6" height="51" rx="3" width="39" x="19" y="11"></rect>
  <path d="M53.98 9.143h-3.97c-.082 0-.155.028-.232.047V5.023C49.778 2.253 47.473 0 44.64 0H10.217C7.384 0 5.08 2.253 5.08 5.023v46.843c0 2.77 2.305 5.023 5.138 5.023h6.037v2.268c0 2.67 2.216 4.843 4.941 4.843H53.98c2.725 0 4.942-2.173 4.942-4.843v-45.17c0-2.671-2.217-4.844-4.942-4.844zM7.11 51.866V5.023c0-1.649 1.394-2.991 3.106-2.991H44.64c1.712 0 3.106 1.342 3.106 2.99v46.844c0 1.649-1.394 2.991-3.106 2.991H10.217c-1.712 0-3.106-1.342-3.106-2.99zm49.778 7.29c0 1.551-1.306 2.812-2.91 2.812H21.195c-1.604 0-2.91-1.26-2.91-2.811v-2.268H44.64c2.833 0 5.138-2.253 5.138-5.023V11.128c.077.018.15.047.233.047h3.968c1.604 0 2.91 1.26 2.91 2.811v45.17z"></path>
  <path d="M38.603 13.206H16.254a1.015 1.015 0 1 0 0 2.032h22.35a1.015 1.015 0 1 0 0-2.032zM38.603 21.333H16.254a1.015 1.015 0 1 0 0 2.032h22.35a1.015 1.015 0 1 0 0-2.032zM38.603 29.46H16.254a1.015 1.015 0 1 0 0 2.032h22.35a1.015 1.015 0 1 0 0-2.032zM28.444 37.587h-12.19a1.015 1.015 0 1 0 0 2.032h12.19a1.015 1.015 0 1 0 0-2.032z"></path>
</svg>
<div class="sr-only">Copy to clipboard</div></button>```yaml
version: '3.6'

services:
  web:
    environment:
      - ENVIRONMENT=dev
      - SECURITY_KEY=random-string-here
      - DB_DRIVER=mysql
      - DB_SERVER=db
      - DB_USER=db
      - DB_PASSWORD=db
      - DB_DATABASE=db
      - DB_PORT=3306
      - DB_SCHEMA=public
      - DB_TABLE_PREFIX=craft_
      - DEFAULT_SITE_URL=https://mysite.ddev.site

      # uploads path
      - ASSET_BASE_PATH=/var/www/html/public/uploads
      - ASSET_BASE_URL=https://mysite.ddev.site/uploads

      #Environment Label
      - CRAFT_ENV_LABEL_PREFIX= Local Site
      - CRAFT_ENV_LABEL_COLOR=#FFFF00
      - CRAFT_ENV_LABEL_TEXT_COLOR=#FF0000

      # site path
      - SITE_PATH=/var/www/html/siteroot
```
```

#### general.php

One final change was to the alias path settings I have in general.php which dynamically sets the path for the uploads folder depending on the environment. Because DDev is using a docker container under the hood, the path is not my windows path but the container path. See the relevant bits of general.php below specifically `basePath`.

```
<button class="absolute z-10 flex items-center justify-center w-8 h-8 -translate-y-1/2  -right-4 -top-4" clipboard="" title="Copy to Clipboard" to="" type="button" x-clipboard.raw="// Dev environment settings
    'dev' => [
        // Dev Mode (see https://craftcms.com/guides/what-dev-mode-does)
        'devMode' => true,
        'allowAdminChanges' => true,
        // 'aliases' => array(
        //     'environment' => 'dev',
        //     'basePath' => 'D:\sites\memoirs',
        //     'baseUrl'  => 'http://memoirs.test',
        // ),
        'aliases' => array(
            'environment' => 'dev',
            'basePath' => '/var/www/html',
            'baseUrl'  => 'http://memoirs.test',
        ),
    ]," x-data="">
	<svg class="h-5 w-5" viewbox="0 0 64 64" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
  <rect fill="#f3f4f6" height="53" rx="3" width="41" x="7" y="2"></rect>
  <rect fill="#f3f4f6" height="51" rx="3" width="39" x="19" y="11"></rect>
  <path d="M53.98 9.143h-3.97c-.082 0-.155.028-.232.047V5.023C49.778 2.253 47.473 0 44.64 0H10.217C7.384 0 5.08 2.253 5.08 5.023v46.843c0 2.77 2.305 5.023 5.138 5.023h6.037v2.268c0 2.67 2.216 4.843 4.941 4.843H53.98c2.725 0 4.942-2.173 4.942-4.843v-45.17c0-2.671-2.217-4.844-4.942-4.844zM7.11 51.866V5.023c0-1.649 1.394-2.991 3.106-2.991H44.64c1.712 0 3.106 1.342 3.106 2.99v46.844c0 1.649-1.394 2.991-3.106 2.991H10.217c-1.712 0-3.106-1.342-3.106-2.99zm49.778 7.29c0 1.551-1.306 2.812-2.91 2.812H21.195c-1.604 0-2.91-1.26-2.91-2.811v-2.268H44.64c2.833 0 5.138-2.253 5.138-5.023V11.128c.077.018.15.047.233.047h3.968c1.604 0 2.91 1.26 2.91 2.811v45.17z"></path>
  <path d="M38.603 13.206H16.254a1.015 1.015 0 1 0 0 2.032h22.35a1.015 1.015 0 1 0 0-2.032zM38.603 21.333H16.254a1.015 1.015 0 1 0 0 2.032h22.35a1.015 1.015 0 1 0 0-2.032zM38.603 29.46H16.254a1.015 1.015 0 1 0 0 2.032h22.35a1.015 1.015 0 1 0 0-2.032zM28.444 37.587h-12.19a1.015 1.015 0 1 0 0 2.032h12.19a1.015 1.015 0 1 0 0-2.032z"></path>
</svg>
<div class="sr-only">Copy to clipboard</div></button>```javascript
// Dev environment settings
    'dev' => [
        // Dev Mode (see https://craftcms.com/guides/what-dev-mode-does)
        'devMode' => true,
        'allowAdminChanges' => true,
        // 'aliases' => array(
        //     'environment' => 'dev',
        //     'basePath' => 'D:\sites\memoirs',
        //     'baseUrl'  => 'http://memoirs.test',
        // ),
        'aliases' => array(
            'environment' => 'dev',
            'basePath' => '/var/www/html',
            'baseUrl'  => 'http://memoirs.test',
        ),
    ],
```
```

#### Final Thoughts

I'm going to start moving away from Mamp Pro with new builds and sites that I'm actively working on. I'll keep Mamp Pro installed for sites relying on PHP 5.4/5.5 since DDev only goes back to php 5.6. Once I no longer need to support these sites I'll be done with Mamp.

**Advantages:**

- Works well for Craft and ExpressionEngine sites - likely for almost any PHP based cms
- Can peek under the hood at how DDev uses docker, allowing you to pick up more about Docker and move to a pure docker setup in the future.
- local domains automatically generated based on folder name so D:/sites/myblog results in my local url as <http://myblog.ddev.site> - this is manually configurable as well.
- Excellent documentation
- only need to know a [few commands](https://ddev.readthedocs.io/en/latest/users/cli-usage/) for day to day work: `ddev start`, `ddev stop`, `ddev restart`, `ddev import-db`, `ddev describe`, and `ddev poweroff`.

**Disadvantages:**

- Running multiple sites at the same time requires manually setting different ports - MAMP does this out of the box and is a clear winner

#### Update

After getting several craft sites up and running with DDev for local development I discovered that I was unable to save entries. On saving the CP hung for a bit and finally returned with an error page.

I did test with an ExpressionEngine site and did not have the same issue - probably because ExpressionEngine isn't using Mutex.

A little googling later and I found the solution in a [github issue](https://github.com/craftcms/cms/issues/4355#issuecomment-498829513).

From your Craft `config/app.php` file, you can use this to set the `isWindows` property of the FileMutex class to `true`.

Once I added this snippet and restarted ddev all was good.

```
<button class="absolute z-10 flex items-center justify-center w-8 h-8 -translate-y-1/2  -right-4 -top-4" clipboard="" title="Copy to Clipboard" to="" type="button" x-clipboard.raw="return [
    'components' => [
        'mutex' => function() {
            $config = craft\helpers\App::mutexConfig();
            $config['isWindows'] = true;
            return Craft::createObject($config);
        },
    ],
];" x-data="">
	<svg class="h-5 w-5" viewbox="0 0 64 64" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
  <rect fill="#f3f4f6" height="53" rx="3" width="41" x="7" y="2"></rect>
  <rect fill="#f3f4f6" height="51" rx="3" width="39" x="19" y="11"></rect>
  <path d="M53.98 9.143h-3.97c-.082 0-.155.028-.232.047V5.023C49.778 2.253 47.473 0 44.64 0H10.217C7.384 0 5.08 2.253 5.08 5.023v46.843c0 2.77 2.305 5.023 5.138 5.023h6.037v2.268c0 2.67 2.216 4.843 4.941 4.843H53.98c2.725 0 4.942-2.173 4.942-4.843v-45.17c0-2.671-2.217-4.844-4.942-4.844zM7.11 51.866V5.023c0-1.649 1.394-2.991 3.106-2.991H44.64c1.712 0 3.106 1.342 3.106 2.99v46.844c0 1.649-1.394 2.991-3.106 2.991H10.217c-1.712 0-3.106-1.342-3.106-2.99zm49.778 7.29c0 1.551-1.306 2.812-2.91 2.812H21.195c-1.604 0-2.91-1.26-2.91-2.811v-2.268H44.64c2.833 0 5.138-2.253 5.138-5.023V11.128c.077.018.15.047.233.047h3.968c1.604 0 2.91 1.26 2.91 2.811v45.17z"></path>
  <path d="M38.603 13.206H16.254a1.015 1.015 0 1 0 0 2.032h22.35a1.015 1.015 0 1 0 0-2.032zM38.603 21.333H16.254a1.015 1.015 0 1 0 0 2.032h22.35a1.015 1.015 0 1 0 0-2.032zM38.603 29.46H16.254a1.015 1.015 0 1 0 0 2.032h22.35a1.015 1.015 0 1 0 0-2.032zM28.444 37.587h-12.19a1.015 1.015 0 1 0 0 2.032h12.19a1.015 1.015 0 1 0 0-2.032z"></path>
</svg>
<div class="sr-only">Copy to clipboard</div></button>```javascript
return [
    'components' => [
        'mutex' => function() {
            $config = craft\helpers\App::mutexConfig();
            $config['isWindows'] = true;
            return Craft::createObject($config);
        },
    ],
];
```
```

<a class="jump-anchor" name="update" style="position:relative;top:-10px;"></a>#### Update

I have run into an issue when trying to use the the Craft CMS CLI which I hadn't seen before. first I did `ddev ssh` which ssh's you into your container and then run any of the craft cli commands for example `./craft help` and then I got this error.

`/usr/bin/env: 'php\r': No such file or directory`

Some googling and I determined that windows was adding hidden characters to the files when I pulled them down. Not a problem before using Ddev but since Ddev is using linux containers it wouldn't recognize the commands. The solution is simple.

First open a terminal and run this command:

`git config --global core.autocrlf tru`

and then you have to re-clone your repository. Yeah that part is not fun. You need to delete your local repository and then clone it from the bitbucket or github. Once you do this everything works as expected.

## Related Articles

[![MAMP Pro for Windows - MySQL Runaway Storage Thumbnail](https://caffeinecreations.ca/uploads/blog/_680x320_crop_center-center_65_none_ns/abstract-art-background-270456.jpg)### MAMP Pro for Windows - MySQL Runaway Storage](https://caffeinecreations.ca/blog/mamp-pro-for-windows-mysql-runaway-storage/)

[![Grouping Entries by First Letter of Last Name Thumbnail](https://caffeinecreations.ca/uploads/blog/_680x320_crop_center-center_65_none_ns/alphabet.jpg)### Grouping Entries by First Letter of Last Name](https://caffeinecreations.ca/blog/grouping-entries-by-first-letter-of-last-name/)

[![Creating a Simple Job Board in Craft CMS Thumbnail](https://caffeinecreations.ca/uploads/hero/_680x320_crop_center-center_65_none_ns/job-board-hero.jpg)### Creating a Simple Job Board in Craft CMS](https://caffeinecreations.ca/blog/creating-a-simple-job-board-in-craft-cms/)
