Instalación de DDEV y despliegue de proyecto Drupal 9 en Ubuntu 20.04
Tags: ddev, drupal, docker, ubuntu
Published: 2021-12-03 11:08:56

Instalación de los componentes necesarios para ejecutar DDEV y crear entornos locales de trabajo de PHP. Docker y Docker Compose son requisitos imprescindibles y los instalaremos con la configuración mínima para que funcione DDEV.

El índice de este tutorial es:

1. Instalación de Docker
2. Instalación de Docker Compose
3. Instalación de DDEV y la plantilla de Drupal 9

## ¿Qué es DDEV?

DDEV es una herramienta de código abierto que facilita la creación de entornos locales de desarrollo PHP. Al montar una instancia en tu servidor, existe la posibilidad de implementar marcos de trabajo de Drupal, WordPress, TYPO3, Backdrop, Magento, Laravel, etc. 

Un importante detalle de DDEV es su naturaleza de entorno local de desarrollo, es decir, no es visible en red. Para que sea accesible desde otro equipo, puedes usar [ngrok](https://ngrok.com) para dotar de URL al entorno.

[Web oficial de DDEV](https://ddev.com)
[Centro de documentación de DDEV](https://ddev.readthedocs.io/en/stable/)

## ¿Qué es Docker?


![Logo de Docker](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/unw4px2tl74kvzdjex2z.png)

Docker es una plataforma que empaqueta software en unidades llamadas "contenedores" incluyendo los requisitos necesarios para ejecutar un proyecto determinado, como por ejemplo configurar una versión concreta de un servidor de base de datos, bibliotecas, java, etc, distinta a la del sistema operativo que lo contiene. Por eso el uso de la palabra "contenedor", porque encapsula dichos requisitos para un desarrollo óptimo de lo que se ejecute en él.

Aunque esta definición de Docker se pueda asimilar a una virtualización, hay que tener en cuenta que la diferencia principal es el menor consumo de recursos en el uso de contenedores con respecto a máquinas virtuales debido a que, en el primer caso, no es necesario instalar un sistema operativo sobre otro tal como ocurre en las virtualizaciones.

[Web oficial de Docker](https://www.docker.com)
[Centro de documentación de Docker](https://docs.docker.com)

## ¿Qué es Docker Compose?

Docker Compose es una herramienta para gestionar varios contenedores a través de un archivo de configuración YAML, permitiendo que, a través de un solo comando, se pueda poner en marcha o eliminar un contenedor.

[Documentación sobre Docker Compose](https://docs.docker.com/compose)


:heart: para @davidjguru , [penyaskito](https://github.com/drud/ddev-contrib/pull/128), [erikaheidi](https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-compose-on-ubuntu-20-04) y [bhogan](https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-20-04).

---

## Instalación de Docker

Actualizamos nuestro sistema para instalar los paquetes más recientes:

```
$ sudo apt update
```

Instalamos los requisitos necesarios:

```
$ sudo apt install build-essential apt-transport-https ca-certificates software-properties-common curl
```

Agregamos la clave GPG del repositorio oficial de Docker:

```
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
```

y, tras el OK, agregamos el repositorio:


```
$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable"
```

En caso de que no actualice repositorios automáticamente, ejecutamos de nuevo:

```
$ sudo apt update
```

Con la actualización anterior, comprobamos que no hay ningún error e instalamos Docker desde el repositorio oficial, no desde los originales de Ubuntu:

```
$ sudo apt install docker-ce
```

Comprobamos si ha sido instalado y ejecutándose si ejecutamos:

```
$ sudo systemctl status docker
```

y obtenemos una salida similar a esta:
```
[sudo] password for daniel:   
● docker.service - Docker Application Container Engine  
     Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)  
     Active: active (running)  since Fri 2021-08-27 19:27:56 CEST; 25min ago  
TriggeredBy: ● docker.socket  
       Docs: https://docs.docker.com  
   Main PID: 736 (dockerd)  
      Tasks: 11  
      Memory: 114.5M  
     CGroup: /system.slice/docker.service  
             └─736 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock  
```
Para el cometido de este tutorial sería suficiente, puedes investigar sobre los comandos de Docker ejecutando

```
$ docker
```

o accediendo a la [documentación oficial dedicada](https://docs.docker.com/engine/reference/commandline/docker).

## Extra

Si al arrancar Docker obtenemos el siguiente error:
```
Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/  >docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.27/containers/json: dial unix /var/run/docker.>sock: connect: permission denied
```
Otorgamos permisos al *user* en el grupo *docker* de la siguiente manera

```
$ sudo usermod -aG docker $USER && sudo reboot
```

forzando a reiniciar para aplicar los cambios.

## Instalación de Docker Compose

Procedemos a la descarga y configuración de permisos para ejecutar Docker Compose.

### Descarga del archivo

A la hora de realizar este tutorial, la última versión corresponde a `2.1.1`, comprueba cuál es la más reciente en el [listado de lanzamientos en GitHub](https://github.com/docker/compose/releases). Sólamente tendrías que cambiar el número. Las variables `$(uname -s)` y `$(uname -m)` eligen tu sistema y arquitectura (32 ó 64 bits), respectivamente.

```
$ sudo curl -L "https://github.com/docker/compose/releases/download/v2.1.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
```

## Permisos

Ajustamos los permisos para que sea ejecutable:

```
$ sudo chmod +x /usr/local/bin/docker-compose
```

Comprobamos la instalación:

```
$ docker-compose --version
```

Debemos tener un resultado similar a:

 > docker-compose version 2.1.1

Así, comprobamos que Docker Compose está correctamente instalado.

## Instalación de DDEV y la plantilla de Drupal 9

![Logos de DDEV y Drupal](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k5ml5hyujztr2n0v9ifj.png)

Dividimos en dos esta parte para mayor claridad.

## Instalación de DDEV

Descargamos el script con los comandos para descargar e instalar DDEV:

```
$ curl -O https://raw.githubusercontent.com/drud/ddev/master/scripts/install_ddev.sh
```

En el siguiente enlace podemos observar el [contenido de este script](https://github.com/drud/ddev/blob/master/scripts/install_ddev.sh).

Otorgamos permisos para que el script sea ejecutable:

```
$ chmod +x install_ddev.sh
```

y ejecutamos con:

```
$ ./install_ddev.sh
```

Durante el proceso, es posible que solicite instalar algunas dependencias o requisitos. Una vez finalizado, ejecuta el siguiente comando para comprobar que está correcto:

```
$ ddev version
```

Obtenemos una salida similar a esta, dependiendo de las versiones y la arquitectura de nuestro sistema:
```
ITEM            VALUE                                                
 DDEV version    v1.18.1                                              
 architecture    amd64                                                
 db              drud/ddev-dbserver-mariadb-10.3:20211017_mysql_arm64 
 dba             phpmyadmin:5                                         
 ddev-ssh-agent  drud/ddev-ssh-agent:v1.18.0                          
 docker          20.10.11                                             
 docker-compose  v2.1.1                                               
 mutagen         0.12.0                                               
 os              linux                                                
 router          drud/ddev-router:v1.18.0                             
 web             drud/ddev-webserver:v1.18.1
```
A través de

```
$ ddev
```

listamos los comandos de `ddev`. Puedes visitar el [centro de documentación](https://ddev.readthedocs.io/en/stable/users/cli-usage/#favorite-commands) para más detalles.

*Nota: Hasta este punto, cualquier instalación con DDEV será igual, por lo que si queremos instalar otras plantillas como Magento, en lugar de Drupal, toda la tarea realizada hasta ahora no es necesario repetirla.*

## Instalación de la plantilla Drupal 9

Creamos y accedemos a la carpeta donde albergaremos el proyecto:

```
$ mkdir miproyecto && cd miproyecto 
```

Dentro de la carpeta raíz, creamos la estructura de directorios de Drupal 9. Ambas opciones ofrecen el mismo resultado, sirviendo su observación para conocer mejor el funcionamiento de DDEV.

- Opción 1

Al escribir en el terminal

```
$ ddev config
```

Nos preguntará la ruta donde queremos guardarla y el tipo de plantilla. En este caso, elegiremos Drupal 9. Marco en negrita lo que he introducido. El resto es la salida de la instalación:
```
daniel@ubuntuserver:~/miproyecto$ ddev config  
Creating a new ddev project config in the current directory (/home/daniel/miproyecto)  
Once completed, your configuration will be written to /home/daniel/miproyecto/.ddev/config.yaml  
   
Project name (miproyecto): Drupalea          

The docroot is the directory from which your site is served.  
This is a relative path from your project root at /home/daniel/miproyecto  
You may leave this value blank if your site files are in the project root   
Docroot Location (current directory):  [He dejado en blanco]   
Found a php codebase at /home/daniel/miproyecto.  
Project Type [backdrop, drupal6, drupal7, drupal8, drupal9, laravel, magento, magento2, php, shopware6, typo3, wordpress] (php): drupal9  
Ensuring write permissions for Drupalea  
No settings.php file exists, creating one  
Existing settings.php file includes settings.ddev.php  
Configuration complete. You may now run 'ddev start'.  
```
Devolviéndonos el terminal. Importante indicar que `Docroot location` lo he dejado en blanco para que la estructura se cree, por defecto, en la carpeta raíz y no sea, por ejemplo, un subdirectorio.

- Opción 2

De antemano, podemos incluir las dos opciones incluidas arriba a través de parámetros:

```
$ ddev config --docroot=web --create-docroot --project-type=drupal9
```

Obtenemos la siguiente salida:
```
Creating a new ddev project config in the current directory (/home/daniel/miproyecto)  
Once completed, your configuration will be written to /home/daniel/miproyecto/.ddev/config.yaml  
  
Created docroot at /home/daniel/miproyecto/web  
You have specified a project type of drupal9 but no project of that type is found in /home/daniel/miproyecto/web  
Ensuring write permissions for miproyecto   
No settings.php file exists, creating one  
Existing settings.php file includes settings.ddev.php  
Configuration complete. You may now run 'ddev start'.  
```
Por ahora, no es necesario ejecutar `ddev start`.

### Descarga de la plantilla Drupal 9 a través de Composer

Una vez tenemos la estructura, y sin salirnos de la carpeta raíz, ejecutamos:

```
$ yes | ddev composer create drupal/recommended-project
```

El "yes" del inicio sirve para automatizar el paso en el que solicita si puede seguir para reescribir la estructura creada en el anterior paso. Al modificar parte del árbol de directorios creado con `ddev config`, es normal que solicite permisos para seguir. 

*Nota: No hay que confundir "Docker Compose", descrito en este tutorial, con "Composer", el administrador para proyectos PHP con el que instalaremos los paquetes de Drupal 9.*

Instalamos **Drush**, una aplicación basada en shell que se utiliza para controlar, manipular y administrar los sitios web de Drupal, además de otros módulos básicos para este CMS como admin_toolbar y devel que añadirán funcionalidades extra de navegación.

```
$ ddev composer require drush/drush drupal/admin_toolbar drupal/devel
```
Obteniendo una salida similar a esta:
```
Using version ^10.6 for drush/drush  
./composer.json has been created  
Running composer update drush/drush  
Loading composer repositories with package information  
Updating dependencies  
Lock file operations: 46 installs, 0 updates, 0 removals  
&nbsp;&nbsp;-Locking chi-teck/drupal-code-generator (1.33.1)  
 ...  
Writing lock file  
Installing dependencies from lock file (including require-dev)  
Package operations: 46 installs, 0 updates, 0 removals  
&nbsp;&nbsp;-Downloading ... Extracting archive  
&nbsp;&nbsp;-Installing ...: Extracting archive  
...  
12 package suggestions were added by new dependencies, use `composer suggest` to see details.  
Package container-interop/container-interop is abandoned, you should avoid using it. Use psr/container instead.  
Generating autoload files  
18 packages you are using are looking for funding.  
Use the `composer fund` command to find out more!  
```
*Nota: Los puntos suspensivos representa la larga lista de paquetes que se van descargando e instalando automáticamente.*

Sobre este tipo de instalación via línea de comandos, tienes más información en la [web oficial de Drupal](https://www.drupal.org/docs/develop/using-composer/using-composer-to-install-drupal-and-manage-dependencies) dedicado a esta materia.

Antes de lanzar la instancia, configuramos la base de datos:

```
$ ddev exec drush si --site-name=Drupaleame --account-name=admin --account-pass=password -y
```

Como último paso antes de obtener una instancia de Drupal 9, lanzamos lo instalado:

```
$ ddev start
```

Obteniendo una salida similar a:
```
Starting Drupalea... 
Building ddev-ssh-agent 
Recreating ddev-ssh-agent ...  
Recreating ddev-ssh-agent ... done 
ssh-agent container is running: If you want to add authentication to the ssh-agent container, run 'ddev auth ssh' to enable your keys. 
Running   Command=ip address show dev docker0
Building db 
Building web 
Creating ddev-Drupalea-db ...  
Creating ddev-Drupalea-db ... done 
Creating ddev-Drupalea-dba ...  
Creating ddev-Drupalea-web ...  
Creating ddev-Drupalea-web ... done 
Creating ddev-Drupalea-dba ... done 
Creating ddev-router ...  
Creating ddev-router ... done 
Ensuring write permissions for Drupalea 
Existing settings.php file includes settings.ddev.php 
Ensuring write permissions for Drupalea 
Successfully started Drupalea 
Project can be reached at https://drupalea.ddev.site https://127.0.0.1:49154 
```
*Nota: El puerto puede ser diferente.* 

- Opción 1, sistema con entorno gráfico

En caso de que el entorno local donde hayamos instalado `DDEV` **tenga escritorio tipo GNOME, KDE, XFCE, etc**, podemos ejecutar lo siguiente desde terminal para lanzar a nuestro navegador el configurador de Drupal:

```
$ ddev launch
```

- Opción 2, sistema sin entorno gráfico

Si hemos instalado DDEV en un servidor sin escritorio y lanzamos `ddev launch`, obtenemos el siguiente error
```
/home/daniel/miproyecto/.ddev/commands/host/launch: line 61: xdg-open: command not found  
Failed to run launch ; error=exit status 127  
```
Como es lógico, al no tener entorno gráfico, xdg-open no se encuentra instalado en el sistema ni objetivo sobre el que ejecutar, que sería un navegador tipo Mozilla Firefox.

En este caso, probamos el navegador **lynx** de la siguiente manera:

Instalamos el navegador desde repositorios de Ubuntu:

```
$ sudo apt install lynx
```

y probamos

```
$lynx drupalea.ddev.site
```

Veremos, en el terminal, el texto de una página de configuración de Drupal.

>**Welcome to Example-Drupal |Example-Drupal (p1 of 2)**  
>&nbsp;&nbsp;&nbsp;#alternate  
>  
>&nbsp;&nbsp;&nbsp;Skip to main content  
>  
>User account menu  
>  
>&nbsp;&nbsp;&nbsp;Show — User account menu Hide — User account menu  
>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* Log in  
>  
>&nbsp;&nbsp;&nbsp;Home  
>&nbsp;&nbsp;&nbsp;Drupaleame  
>  
>Main navigation  
>  
>&nbsp;&nbsp;&nbsp;Show — Main navigation Hide — Main navigation  
>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* Home  
>  
>Welcome to Drupaleame  
>  
>&nbsp;&nbsp;&nbsp;No front page content has been created yet.  
>&nbsp;&nbsp;&nbsp;Follow the User Guide to start building your site.  
>&nbsp;&nbsp;&nbsp;Subscribe to  

A partir de ahora, con Docker, Docker Compose y DDEV ya presentes en nuestro equipo, podemos probar otras plantillas como WordPress o Magento a través de DDEV.


---
Foto: "[Containers](https://www.flickr.com/photos/60132504@N08/5939008153)" by tsuna72 is licensed with [CC BY 2.0](https://creativecommons.org/licenses/by/2.0/)