Con este artículo voy a empezar una pequeña serie de artículos sobre cómo desarrollar una aplicación utilizando Docker como nuestro entorno de desarrollo en local. En este primer post nos enfocaremos en crear, configurar y levantar nuestro entorno Docker.
¿Por qué Docker?
Según la tipología de nuestros proyectos y las necesidades de nuestros clientes, necesitamos disponer de entornos de desarrollo rápidos de configurar, levantar y escalar, en definitiva, entornos ágiles.
En los últimos 15 años la evolución en el mundo del desarrollo de aplicaciones web ha sido vertiginosa y con ella multitud de herramientas llegaron para facilitarnos la vida. Y la verdad es que hay multitud de opciones para todos los gustos. Entornos en local utilizando herramientas como XAMPP, WAMP o MAMP, utilizar VirtualBox o VMWare para crear máquinas virtuales de desarrollo, utilizar Vagrant para facilitar la configuración y el despliegues de nuestros entornos virtuales y el uso de entornos basados en contenedores, concretamente Docker.
Pero ¿Qué nos ofrece Docker?
Hasta ahora veníamos utilizando Vagrant con Virtualbox como nuestro entorno de desarrollo, pero con el tiempo han ido surgiendo carencias que necesitábamos resolver y se traducían en utilizar una herramienta que utilice eficientemente los recursos de nuestros equipos aportándonos agilidad y una mayor productividad en nuestros desarrollos.
Docker nos ofrece:
- Uso de los recursos nativos del sistema
- Rapidez de despliegues de entornos
- Entornos escalables
- Alta portabilidad de los entornos de desarrollo
- Entornos enfocados a proyectos
Crear un entorno de desarrollo local con Docker
A continuación vamos a crear una aplicación desde cero con un entorno de desarrollo portable. Para ello solamente es necesario tener Docker instalado en nuestro sistema anfitrión, tu PC o portátil, sea Windows, Linux o MacOS.
Arquitectura de nuestro entorno
Nuestro proyecto va a tener la siguiente estructura:
Definición del entorno con Docker Compose
En el archivo docker-compose.yml vamos a declarar y definir nuestros servicios, uno dedicado para la base de datos y otro para el servidor web.
version: '3' services: db: container_name: ${APP_NAME}-database image: ${DB_PROVIDER}:${DB_VERSION} environment: MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD} MYSQL_DATABASE: ${DB_NAME} MYSQL_USER: ${DB_USER} MYSQL_PASSWORD: ${DB_PASSWORD} volumes: - db_volume:/var/lib/mysql ports: - ${DB_PORT}:3306 networks: net: ipv4_address: 172.21.1.2 www: build: context: .docker/www args: - PHP_VERSION=${PHP_VERSION} container_name: ${APP_NAME}-www command: ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"] tty: true links: - db:${DB_PROVIDER} volumes: - ${APP_DIR}:/var/www/html:cached ports: - ${HTTP_PORT}:80 - ${HTTPS_PORT}:443 networks: net: ipv4_address: 172.21.1.3 networks: net: driver: bridge ipam: config: - subnet: 172.21.1.0/24 volumes: db_volume:
Creando nuestro propio Dockerfile
Nuestro servicio dedicado para el servidor web utilizará un archivo Dockerfile, en el que ampliaremos una imagen Docker ya predefinida.
# Base image FROM ubuntu:18.04 ARG PHP_VERSION # Update repositories index RUN apt update --fix-missing && apt upgrade -y # Install util tools RUN ln -snf /usr/share/zoneinfo/UTC /etc/localtime && echo "UTC" > /etc/timezone RUN apt install -y apt-utils git rsync nano vim unzip curl wget software-properties-common mysql-client # Install Ondrej PHP Multiversions RUN add-apt-repository ppa:ondrej/php RUN add-apt-repository ppa:ondrej/apache2 RUN apt-get update RUN apt-get install -y php$PHP_VERSION # Install Apache RUN apt-get install -y apache2 # Install PHP extensions RUN apt-get install -y -m php$PHP_VERSION-cli \ php$PHP_VERSION-dev \ php$PHP_VERSION-common \ php$PHP_VERSION-json \ php$PHP_VERSION-intl \ php$PHP_VERSION-curl \ php$PHP_VERSION-mysql \ php$PHP_VERSION-gd \ php$PHP_VERSION-imagick \ php$PHP_VERSION-ldap \ php$PHP_VERSION-soap\ php$PHP_VERSION-zip \ php$PHP_VERSION-mbstring \ php$PHP_VERSION-bcmath \ php$PHP_VERSION-xml \ php$PHP_VERSION-imap \ php$PHP_VERSION-bz2 # Install NodeJS and NPM RUN apt-get install -y nodejs npm # Install Composer RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin/ --filename=composer # Config Apache ENV APACHE_RUN_USER www-data ENV APACHE_RUN_GROUP www-data ENV APACHE_LOG_DIR /var/log/apache2 RUN chown www-data:www-data -R /var/www RUN chmod -R 755 /var/www COPY config/000-default.conf /etc/apache2/sites-available/000-default.conf COPY config/php.ini /etc/php/$PHP_VERSION/apache2/php.ini RUN a2enmod rewrite headers RUN service apache2 start WORKDIR /var/www/html EXPOSE 80 EXPOSE 443
Configurando nuestro entorno Docker
En el archivo .env definiremos las variables de configuración para nuestro entorno Docker. Este paso puede omitirse si queremos introducir todos estos valores directamente en el archivo docker-compose.yml, pero de esta forma si queremos alojar nuestro proyecto en algún repositorio tendremos expuestas variables de tipo credencial.
APP_NAME=app APP_DIR=. HTTP_PORT=80 HTTPS_PORT=443 DB_PORT=3306 PMA_PORT=8080 DB_PROVIDER=mariadb DB_VERSION=10.2 DB_ROOT_PASSWORD=root DB_USER=developer DB_PASSWORD=developer DB_NAME=appdb PHP_VERSION=7.1
Levantando nuestro nuestro entorno Docker
Una vez tenemos ya configurado nuestro entorno, abrimos la terminal y situándonos en la raíz de nuestro proyecto ejecutamos el siguiente comando:
docker-compose up --build -d
Este comando levanta nuestro entorno de trabajo, construyendo si fuera necesario y en segundo plano. Equivale a ejecutar los comandos:
docker-compose build && docker-compose up -d