DEV Community

Cover image for Docker LAMP Stack
jay-mj
jay-mj

Posted on • Edited on

Docker LAMP Stack

Good day!
This is my first post on the DEV blog, I'm so glad I joined this amazing resource!

There are many things in development that may be of interest to specialists of different categories, but I decided to talk about cases from my practice of creating a web environment.
I apologize for some confusion in the text of this article, in view of the correction of the turns of the native speech through machine translation.

There was a time when I used XAMPP on a classic operating system. Then Windows 10 came out and small-soft corporation began to aggressively impose it even on lowest-level calculators. Software hangs and telemetry collection on an astronomical scale were concreted into the foundation of nature and all desire to seek further compromises in this madness disappeared. So I liked Linux as an endless expanse for learning the intricacies and nuances of system administration and data processing. A pleasant asset for me was the fact that the Docker, which became the basis for dynamic virtualization, was developed from a Linux-like OS. Based on this, I decided to combine the routine of daily work with continuous learning in the basics of data development and administration.

Since changing the working environment, in a dense stream of routine tasks, was an unaffordable luxury for me, I decided to combine access to a single database from XAMPP and Docker at the same time. To be able to switch, if necessary, disks from Windows and Linux, keeping the program settings in a single way.


DISCLAIMER: This article is an example of my experience, I do not urge you to repeat this in practice, maybe the steps described in this article will help someone to understand in more detail the nuances of setting up the required environment
* READ THE ARTICLE FIRST
* THEN TRY IF YOU WANT BY YOURSELF
* DON'T FORGET TO MAKE BACKUPS!
Thank you all for your attention)

On the Windows side (ntfs HDD) the XAMPP tool is used.

Let's explore some defaults...

  • MYSQL default DB location is:
C:\xampp\mysql\data
Enter fullscreen mode Exit fullscreen mode

You can find your actual DB folder by following command (ex. at phpmyadmin):

SELECT @@datadir
Enter fullscreen mode Exit fullscreen mode

or check datadir parameter of my.ini file located in:

C:\xampp\mysql
Enter fullscreen mode Exit fullscreen mode
  • htdocs default folder location is:
C:\xampp\htdocs
Enter fullscreen mode Exit fullscreen mode

This path is specified in DocumentRoot line of the httpd.conf file

  • To be able to use the XAMPP MYSQL database and htdocs folders on both Windows & Linux systems, I moved them to the other drive prudently correcting the above datadir & DocumentRoot parameters
D:\DB\mysql\data
D:\Projects\htdocs
Enter fullscreen mode Exit fullscreen mode

I rebooted Windows to make sure the new settings were accepted without error, phpmyadmin are logged in successfully, I have no password for development use...

Say Hello to Bill
Say Bye to Windows 10


On the Linux side (ext4 HDD) the Docker tool is used.

  • At first we need to install ntfs drives support and one handy utility "blkid" - if it not present in the system for some reasons:
$ sudo apt update && sudo apt install -y util-linux ntfs-3g
Enter fullscreen mode Exit fullscreen mode

Just keep in mind that Linux is widely open to solving many tasks in many different ways, so the commands used in my case are for my specific case, and you can use more preferable alternative ways to do the same

  • Create a mount point for our shared ntfs hard drive:
$ sudo mkdir /media/paste-your-username-here/point-folder 
$ cd /media/paste-your-username-here/ 
$ sudo chown paste-your-username-here point-folder
Enter fullscreen mode Exit fullscreen mode

Replace paste-your-username-here with your actual user name
The first command creates a directory for the shared drive
Then we go to the current user's disk mount directory
and set the owner for this folder as the current user

  • Now we need to discover UUID of our shared ntfs hard drive, to set its auto mounting options:
$ sudo blkid
Enter fullscreen mode Exit fullscreen mode

You should see something like this:

/dev/sdb1: BLOCK_SIZE="512" UUID="BCBF273CHE84F05E" TYPE="ntfs" PARTUUID="8b2f7e1d-01"
Enter fullscreen mode Exit fullscreen mode

so the string between UUID and TYPE words is our needed combination...

  • Once UUID is found we need to write mounting rule for this drive, mount options are specified in the file called fstab it is located in etc directory...
$ sudo vim /etc/fstab
Enter fullscreen mode Exit fullscreen mode

You will see a current attached drives table. You need to go to the end of file and add one string such following:

UUID=BCBF273CHE84F05E   /media/username/point-folder   ntfs-3g         auto,defaults,permissions,uid=1000,gid=1000,umask=000,nofail,errors=continue,exec 0 0
Enter fullscreen mode Exit fullscreen mode
  • IMPORTANT: read & modify this file very carefully, don't forget to make backups
  • replace UUID value with yours obtained with blkid command
  • replace username to yours
  • uid & gid tags are setting access to the shared drive
  • nofail, errors=continue will skip any mount errors on system boot in case of missing drive or other cases
  • exec tag allows to perform scripts execution on the shared drive
  • you can also set umask tag with 022 value - it will reset user rights of all drive contents to unix 0755 (rwx-rx-rx) format, but in this case I prefer to make it simpler, as 000 value which corresponds to 0777 (rwx) full access format
  • Refresh mounted drives can be done with following command:
$ sudo mount -a
Enter fullscreen mode Exit fullscreen mode

But I prefer to reboot the system and see how it starts at all, it is very exciting step because inaccurate fstab modifying can bring you blank screen on boot ^__^
At last, once system is started...

cat being trapped


We begin to create our docker project

assume that you're already set up the Docker & docker-compose utilities. Otherwise, the description of this step will take too long and distract attention from the original topic of the article
Let's check installed components by command:

$ docker -v && docker-compose -v
Enter fullscreen mode Exit fullscreen mode

In my case the stdout looks like so:

Docker version 20.10.4+dfsg1, build d3cb89e
docker-compose version 1.25.0, build unknown
Enter fullscreen mode Exit fullscreen mode
  • As we mentioned before, our shared drive contains following folders:
ls -lah /media/username/point-folder 
drwxrwxrwx  1 username username 4.0K Sep  7  2020 'DB'
drwxrwxrwx  1 username username 4.0K Sep  7  2020 'Projects'
Enter fullscreen mode Exit fullscreen mode

We will attach them into our docker containers, so the Docker LAMP Stack will use real XAMPP folders

  • Create & Get in to our project folder:
$ cd /media/username/point-folder/Projects
$ mkdir lamp && cd $_
Enter fullscreen mode Exit fullscreen mode
  • as the base of my Docker LAMP Stack image I've use such an awesome github project:
$ git clone https://github.com/sprintcube/docker-compose-lamp .
Enter fullscreen mode Exit fullscreen mode
I've made some changes on it
  • Let's take a first look on the lamp stack project structure:
ls /media/username/point-folder/Projects/lamp
bin  config  data  docker-compose.yml  logs  sample.env  www
Enter fullscreen mode Exit fullscreen mode
  • bin folder contains Dockerfiles which would be used to build our services:
./bin/mysql/Dockerfile:
FROM mariadb
Enter fullscreen mode Exit fullscreen mode
./bin/webserver/Dockerfile:
FROM php:7.3-apache

RUN apt-get -y update --fix-missing
RUN apt-get -y upgrade

RUN apt-get install -y apt-utils nano wget dialog

RUN apt-get install -y --fix-missing apt-utils build-essential git curl libcurl4 libcurl4-nss-dev zip libzip-dev

RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

RUN pecl install xdebug
RUN docker-php-ext-enable xdebug

RUN apt-get install -y libmcrypt-dev
#RUN docker-php-ext-install mcrypt
RUN pecl install mcrypt && docker-php-ext-enable mcrypt

RUN apt-get install -y libsqlite3-dev libsqlite3-0 default-mysql-client
RUN docker-php-ext-install pdo_mysql 
RUN docker-php-ext-install pdo_sqlite
RUN docker-php-ext-install mysqli

RUN docker-php-ext-install curl
RUN docker-php-ext-install tokenizer
RUN docker-php-ext-install json

RUN apt-get install -y zlib1g-dev
RUN docker-php-ext-install zip

RUN apt-get install -y libicu-dev
RUN docker-php-ext-install -j$(nproc) intl

RUN docker-php-ext-install mbstring

RUN apt-get install -y libfreetype6-dev libjpeg62-turbo-dev libpng-dev
RUN docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ 
RUN docker-php-ext-install -j$(nproc) gd

RUN a2enmod rewrite headers

Enter fullscreen mode Exit fullscreen mode
  • config folder contains specific user configurations which represents Windows serices values from XAMPP (for instance)
  • logs folder for error & server-access reports
  • data folder are linked to the XAMPP MYSQL database in our case it corresponds to:
/media/username/point-folder/DB/mysql/data
Enter fullscreen mode Exit fullscreen mode
  • www corresponds to XAMPP htdocs folder:
/media/username/point-folder/Projects/htdocs
Enter fullscreen mode Exit fullscreen mode
  • sample.env is a template where defined some very necessary system paths
  • and the main guest of the project... docker-compose.yml file, which contains all set of the instructions to assemble LAMP Stack properly:
version: "3"

services:
  webserver:
    build: 
      context: ./bin/webserver
    container_name: 'lamp-webserver'
    restart: 'on-failure'
    ports:
      - "80:80"
      - "443:443"
    links: 
      - mysql
    volumes: 
      - ${DOCUMENT_ROOT-./www}:/var/www/html
      - ${PHP_INI-./config/php/php.ini}:/usr/local/etc/php/php.ini
      - ${VHOSTS_DIR-./config/vhosts}:/etc/apache2/sites-enabled
      - ${LOG_DIR-./logs/apache2}:/var/log/apache2
  mysql:
    build: ./bin/mysql
    container_name: 'lamp-mysql'
    restart: 'on-failure'
    ports:
      - "3306:3306"
    volumes: 
      - ${MYSQL_DATA_DIR-./data/mysql}:/var/lib/mysql
      - ${MYSQL_LOG_DIR-./logs/mysql}:/var/log/mysql
      - ./config/mysql/my.cnf:/etc/mysql/my.cnf
      - /etc/localtime:/etc/localtime:ro
    environment:
      # MYSQL_ROOT_PASSWORD: ''
      MYSQL_DATABASE: <place-your-db-name-here>
      MYSQL_USER: root
      # MYSQL_PASSWORD: ''
  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    container_name: 'lamp-phpmyadmin'
    links:
      - mysql
    environment:
      PMA_HOST: mysql
      PMA_PORT: 3306
    ports:
      - '8080:80'
    volumes: 
      - /sessions
      - ./config/phpmyadmin/phpmyadmin-misc.ini:/usr/local/etc/php/conf.d/php-phpmyadmin.ini
  redis:
    container_name: 'lamp-redis'
    image: redis:latest
    ports:
      - "6379:6379"
Enter fullscreen mode Exit fullscreen mode

Read this file carefully

  • notice how user-configuration & log files are attached to the stack containers
  • MYSQL passwords are commented out, because I'm not using them on development
  • VARIABLES of this file are defined in env file

Assemble the LAMP Stack

$ docker-compose up --build -d
Enter fullscreen mode Exit fullscreen mode

Check the execution result on container status:

$ docker ps -a
Enter fullscreen mode Exit fullscreen mode

My stdout is:

5cf0a5b46b18   lamp_webserver            "docker-php-entrypoi…"   1 minute ago   Up 8 seconds   0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp   lamp-webserver
538243f42ab2   phpmyadmin/phpmyadmin         "/docker-entrypoint.…"   1 minute ago   Up 6 seconds   0.0.0.0:8080->80/tcp                       lamp-phpmyadmin
5fe638335f1a   377ad5bc26fe                  "docker-entrypoint.s…"   1 minute ago   Up 1 second    0.0.0.0:3306->3306/tcp                     lamp-mysql
31e73c59abaf   redis:latest                  "docker-entrypoint.s…"   1 minute ago   Up 7 seconds   0.0.0.0:6379->6379/tcp                     lamp-redis

Enter fullscreen mode Exit fullscreen mode

Victory is My!

If everything is fine you could go to the browser and type:
http://localhost:8080
Enter fullscreen mode Exit fullscreen mode

PHPMyAdmin interface will appear, you can use root account to login, we're not provide any password in our file

http://localhost/site/index.php
Enter fullscreen mode Exit fullscreen mode

Apache also ready to use on port 80, replace site with name of your early created project, and happy to coding!


debugging

if something goes wrong you can:
  • Inspect containers for its own settings:
   $ docker inspect 5fe6
Enter fullscreen mode Exit fullscreen mode

5fe6 in this case is the beginning of the hash of the mysql container

  • View logs of returned errors:
   $ docker logs 5fe6
Enter fullscreen mode Exit fullscreen mode
  • Login into container to manually set necessary modifications:
   $ docker exec -it 5fe6 /bin/bash
Enter fullscreen mode Exit fullscreen mode

The 5fe6 container shell will appear, use exit command to logout

  • If you're making changes in the structure of any Dockerfiles or docker-compose.yml do not forget to delete previously created containers and in some cases unused images, to gain some free space:
   $ docker image prune -a
   $ docker container prune
Enter fullscreen mode Exit fullscreen mode

Be careful with this command it will removes all unused images and stopped containers!


Conclusion

While I was practicing on this project, it was not as big as it looks now. I hope you guys will succeed in development and you will be able to gain the necessary experience and create great projects! Thanks to everyone who read this article to the end! Good luck!

Top comments (1)

Collapse
 
edywladson profile image
Edy Wladson • Edited

It worked perfectly, congratulations on the post.
But would you have tips on how to use pgp debuh in VS Code and also in PHPStorm?

I am using WSL2 (Ubuntu 20.04)