Skip to main content

LAMP on Docker: Quick Start

This post describes the steps to build and run a standard LAMP stack using docker-compose.

You can check Mike Zazon’s great article How to use PHP, Apache, MySQL within Docker containers for more detail. I have simply followed it, then added some MySQL parts and so on.

1. prepare files

.
├── apache
│   ├── Dockerfile
│   └── demo.apache.conf
├── docker-compose.yml
├── mysql
│   ├── Dockerfile
│   └── init
│       └── 1_users.sql
├── php
│   └── Dockerfile
└── public_html
    └── index.php

1a. apache/Dockerfile

FROM httpd:2.4.33-alpine
RUN apk update; \
    apk upgrade;
# Copy apache vhost file to proxy php requests to php-fpm container
COPY demo.apache.conf /usr/local/apache2/conf/demo.apache.conf
RUN echo "Include /usr/local/apache2/conf/demo.apache.conf" \
    >> /usr/local/apache2/conf/httpd.conf

1b. apache/demo.apache.conf

ServerName localhost

LoadModule deflate_module /usr/local/apache2/modules/mod_deflate.so
LoadModule proxy_module /usr/local/apache2/modules/mod_proxy.so
LoadModule proxy_fcgi_module /usr/local/apache2/modules/mod_proxy_fcgi.so

<VirtualHost *:80>
    # Proxy .php requests to port 9000 of the php-fpm container
    ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://php:9000/var/www/html/$1
    DocumentRoot /var/www/html/
    <Directory /var/www/html/>
        DirectoryIndex index.php
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
    
    # Send apache logs to stdout and stderr
    CustomLog /proc/self/fd/1 common
    ErrorLog /proc/self/fd/2
</VirtualHost>

1c. docker-compose.yml

version: "3.2"
services:
  apache:
    build: './apache/'
    depends_on:
      - php
      - mysql
    networks:
      - frontend
      - backend
    ports:
      - "80:80"
    volumes:
      - ./public_html/:/var/www/html/
  php:
    build: './php/'
    networks:
      - backend
    volumes:
      - ./public_html/:/var/www/html/
  mysql:
    build: './mysql/'
    networks:
      - backend
    environment:
      - MYSQL_ROOT_PASSWORD=rootpassword
      - MYSQL_DATABASE=test_db
      - MYSQL_USER=devuser
      - MYSQL_PASSWORD=devpass
networks:
  frontend:
  backend:

1d. mysql/Dockerfile

from mysql:5.7

COPY init/* /docker-entrypoint-initdb.d/

RUN echo 'alias db="mysql -u${MYSQL_USER} -p${MYSQL_PASSWORD} ${MYSQL_DATABASE}"' >> ~/.bashrc

CMD ["mysqld"]

1e. mysql/init/1_users.sql

create table users (
  id int auto_increment,
  nickname varchar(100) unique not null,
  email varchar(320) not null,
  password_hash varchar(128) not null,
  created datetime not null DEFAULT CURRENT_TIMESTAMP,
  modified datetime not null DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

  primary key(id)
);

insert into users (nickname, email, password_hash) values
('test1', 'test1@example.com', sha2('password', 512)),
('test2', 'test2@example.com', sha2('password', 512)),
('test3', 'test3@example.com', sha2('password', 512));

1f. php/Dockerfile

FROM php:7.2.7-fpm-alpine3.7
RUN apk update; \
    apk upgrade;
RUN docker-php-ext-install mysqli

1g. public_html/index.php

<?php 
$host = 'mysql';
$user = 'root';
$pass = 'rootpassword';
$conn = new mysqli($host, $user, $pass, 'test_db');

if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
} 
echo "Connected to MySQL successfully!<br>";

$sql = "SELECT * FROM users";
if ($result = $conn->query($sql)) {
    while ($row = $result->fetch_assoc()) {
        echo $row["nickname"] . ', ' . $row["email"] . "<br>";
    }
    $result->close();
}

$conn->close();
echo "done<br>";

2. build and run

docker-compose up --build

3. access

http://localhost/

You will see the records selected on the database.

Connected to MySQL successfully!
test1, test1@example.com
test2, test2@example.com
test3, test3@example.com
done

Comments

Popular posts from this blog

Selenide: Quick Start

Minikube Installation for M1 Mac

Three.js Quick Start - Run Spinning-Cube Example