Docker LAMP Stack With Composer PSR-4 Autoloading – Apache Server
Tags: docker, php, psr4, apache
Published: 2024-05-03 16:06:09

I wanted to create a Docker Lampstack with Composer PSR-4 Autoloading.

Here are my requirements:

-     Run on Ubuntu 22.04 or Windows
-     Apache Server
-     PhpMyadmin
-     PHP Version 8.3
-     Mysql Version 8
-     Composer
-     PS4- Autoloading
-     PHPMailer

These are the steps to run Composer and implement PSR-4 Autoloading in Docker:

Install Docker on your system if you don't already have it installed.

**Step 1: Create a new project directory:**

```yml
mkdir lampstack-project
cd lampstack-project
```

**Step 2: Create a file named docker-compose.yml in the project directory:**

```yml
touch docker-compose.yml
```

**Step 3: Open the file using your preferred text editor:**

```yml
nano docker-compose.yml
```

**Step 4: Setting up the Services
In this step, we'll define the services we need for our project. We'll be using 3 services:**

-     **_db_**: This service is for our database, which will run on the MySQL image.
-     **_web_**: This service is for our web server, which will run on the Apache image.
-     **_phpmyadmin_**: This service provides a graphical user interface to our MySQL database. It runs on the phpMyAdmin image.

Add the following contents to the **_docker-compose.yml_** file.

```yml
name: myapp

services:
  db:
    image: mysql:8
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: mydatabase
      MYSQL_USER: myuser
      MYSQL_PASSWORD: mypassword
    ports:
      - "3306:3306"
  web:
    build: .
    volumes:
      - ./:/var/www/html/
      - '/var/www/html/vendor' # Prevents first volume from overwriting vendor directory.
    ports:
      - "8000:80"
    links:
      - db
  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    ports:
      - "8080:80"
    environment:
      PMA_HOST: db
      PMA_PORT: 3306
      PMA_ARBITRARY: 1
    links:
      - db

```
Step 5: Writing the Dockerfile
In this step, we'll write a Dockerfile that will define how our web service will be built.

This dockerfile sets up a basic PHP environment and installs the necessary PHP extensions. It also installs Composer and runs **_composer install_** to install the dependencies listed in your **_composer.json_** file.

Create a new Dockerfile with the following contents.

```yml
touch dockerfile
nano dockerfile
```

```yml
FROM php:8.3.6-apache

# Install dependencies and PHP extensions
RUN apt-get update && apt-get upgrade -y && \
    apt-get install -y libzip-dev zip nano && \
    docker-php-ext-install pdo pdo_mysql && \
    pecl install xdebug && docker-php-ext-enable xdebug && \
    apt-get install -y libfreetype6-dev libjpeg62-turbo-dev libpng-dev && \
    docker-php-ext-configure gd --with-freetype --with-jpeg && \
    docker-php-ext-install -j$(nproc) gd && \
    docker-php-ext-install zip

# Install Composer
COPY --from=composer/composer:latest-bin /composer /usr/bin/composer

# Set the COMPOSER_ALLOW_SUPERUSER environment variable
ENV COMPOSER_ALLOW_SUPERUSER 1

# Copy the code into the container
COPY . /var/www/html/

# Set the working directory to /var/www/html/
WORKDIR /var/www/html/

# Install PHPMailer
RUN composer require phpmailer/phpmailer

# Set Apache document root to /var/www/html/public
ENV APACHE_DOCUMENT_ROOT=/var/www/html/public
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf
RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf

# Run composer Install
RUN composer install
```

**Step 6: Adding the composer.json File**
In this step, we'll add a composer.json file that specifies the dependencies for our project.

Create a **_composer.json_** file in your project root with the following contents:

```yml
touch composer.json
nano composer.json
```

Paste this into your **_composer.json_**. I have added some package dependency's to demonstrate the automatic installation of Composer packages.

```json
{
    "autoload": {
        "psr-4": {
            "App\\": "app/"
        }
    }
}
```

**Step 7: Create a public directory & index.php in the project directory**

```yml
mkdir public && touch public/index.php
```

**Step 8: Open editor and add this to PHP code to index.php for Autoloading.**

```yml
nano public/index.php
```

```php
<?php

require_once '../vendor/autoload.php';

$controller = new App\Controllers\ExampleController();
echo $controller->index();
```

**Step 9: Creating the ExampleController**
In this step, we'll create an ExampleController that will handle the requests to our web service. This controller will return a simple message to confirm that our setup is working.

Create the Controller Directory and file **_ExampleController.php_** and open **_ExampController.php_** in your editor.

```yml
mkdir -p app/Controllers
touch app/Controllers/ExampleController.php
```

* Windows Use:

```yml
mkdir app\Controllers
touch app/Controllers/ExampleController.php
```

**Step 10: Open editor & add the following PHP code to _ExampleController.php_**

```yml
nano app/Controllers/ExampleController.php
```

```php
<?php

namespace App\Controllers;

class ExampleController
{
    public function index()
    {
        return 'Hello World!';
    }
}
```

**Step 11: Running the Docker Compose File**

In this step, we'll run the docker-compose file to start the services we defined in step 4. The code for the docker-compose file will start the services and link them together, allowing them to communicate with each other.

Run the **_docker-compose up_** command from the directory where your **_docker-compose.yml_** file is located.

**_docker-compose up_** not only starts the containers defined in the **_docker-compose.yml_** file, but also builds the images if they do not already exist. The up command checks if the image specified in the docker-compose.yml file is present in the local system, and if it is not found, the image is built using the **_Dockerfile_** specified in the same file.

```yml
docker-compose up
```

This will run your PHP application with PSR-4 autoloading enabled via Composer, inside an Apache server and linked with a MySQL 8 database.

Composer should have run and installed the sample packages.

**Step 12: Testing the Setup**

In this step, we'll test our setup by making a request to our web service. If everything is set up correctly, we should see the message returned by the ExampleController.

Open a web browser and go to http://localhost:8000. You should see the output of your PHP script.

To access phpMyAdmin, go to http://localhost:8080 in your web browser. You will be prompted to log in with a username and password.

The username is "myuser" and the password is "mypassword", as specified in the environment variables of the "db" service in the **_docker-compose.yml_** file.

After logging in to phpMyAdmin, you should be able to see the "mydatabase" database and make any necessary changes to it through the phpMyAdmin interface.

**PhpMyAdmin Logins**

Server: db
User: myuser
Pasword:mypassword

User: root
Pasword:root

The "db" is specified in the PMA_HOST environment variable in the phpmyadmin service, and the port is specified in the ports section of the db service. When you access PHPMyAdmin on port 8080, it will connect to the database service running on db:3306.
Docker Container Terminal

To get a terminal in the Docker Container you can run the following command. You will be the root user so you can do anything you want from the terminal within your container including adding or deleting Composer Packages.

```yml
# Get a terminal
docker exec -it lampstack-project-web-1 /bin/bash

# To get out of the terminal shell, type 
exit
```

When you're done, you can stop the containers using the following command:

```yml
docker-compose down
```