This post was originally published on Siv Scripts
Being a Software Engineer isn't just about being effective in a specific programming language, it's about being able to solve any given problem using the tools at hand.
This week at work I have to extend the functionality of a WordPress plug-in so it can fit into our microservices-based backend architecture. This means learning enough PHP to write some production-grade code.
I don't want to install PHP on my local machine so this is the perfect use case for Docker! In this Quick Hit, I will describe how to create a containerized PHP + MySQL development environment using Docker Compose.
The LAMP Stack is back!
Instructions
We'll start by creating a folder for this project:
mkdir lamp-stack && cd lamp-stack
Create another subdirectory,
/php
which contains the followingindex.php
file:
<!-- ./php/index.php -->
<html>
<head>
<title>Hello World</title>
</head>
<body>
<?php
echo "Hello, World!";
?>
</body>
</html>
- Populate
docker-compose.yml
with the following configuration:
# ./docker-compose.yml
version: '3'
services:
db:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: my_secret_pw_shh
MYSQL_DATABASE: test_db
MYSQL_USER: devuser
MYSQL_PASSWORD: devpass
ports:
- "9906:3306"
web:
image: php:7.2.2-apache
container_name: php_web
depends_on:
- db
volumes:
- ./php/:/var/www/html/
ports:
- "8100:80"
stdin_open: true
tty: true
- Our directory structure should look as follows:
$ tree
.
├── docker-compose.yml
└── php
└── index.php
- Execute
docker-compose up -d
in the terminal and load http://localhost:8100/ in your browser.
Notes
- We use port-forwarding to connect to the inside of containers from our local machine.
- webserver:
http://localhost:8100
- db:
mysql://devuser:devpasslocalhost:9906/test_db
- webserver:
- Our local directory,
./php
, is mounted inside of the webserver container as/var/www/html/
- The files within in our local folder will be served when we access the website inside of the container
Top comments (7)
Thanks for the article. While trying to run through the above I ran into this error
ERROR: In file './docker-compose.yml', service must be a mapping, not a NoneType.
which I solved by updating docker-compose.yml to this
The indentation matters and this finally got it working. Hope this helps anyone else trying to use this.
Thanks for the heads up!
Didn't realize the indentation got messed up as I copied this over. It has been corrected.
I'm just getting in to Docker so I'm actually glad it had that issue so I'm now aware that I have to get the indentation correct. :)
When working with the database from the application, I get the following:
Fatal error: Uncaught Error: Call to undefined function mysqli_connect() in /var/www/html/index.php:6 Stack trace: #0 {main} thrown in /var/www/html/index.php on line 6
Connection code:
<?php
$servername = "localhost:9906";
$username = "devuser";
$password = "devpass";
$dbname = "test_db";
$conn = mysqli_connect($servername, $username, $password, $dbname) or die("Fatal error: " . mysqli_connect_error());
if (mysqli_connect_errno()) {
printf("Fatal error: %s\n", mysqli_connect_error());
exit();
}
?>
With the help of mysqlworkbench i can connect and work with the database!
Tell me where I went wrong and why it doesn't work?
Thanks, Aly. I have a question: if the container is restarted, are the MySQL databases lost? In other words, is there persistence in the database?
The setup I describe above stores data inside of the container. This data is lost when the container is deleted (
docker-compose down
)You could mount a volume so the data is persisted on your local machine.
Looking at hub.docker.com/_/mysql/ (search for Where to Store Data), we can update the
docker-compose.yml
with another volume mount as follows:Now data will persist in the
./sql
directory.Thank you very much!