I will give you a brief introduction to setting up an environment for developing a PHP application using MongoDB.
I use the environment for local development and release the application on the server if the application is not business-critical.
For example, one application reads and processes AWS price lists (in JSON format), stores them in a database, and uses the data to process, report, and publish them to the Web site for review.
The environment uses
- Docker-compose
- Nginx web server
- PHP 8.2 (PHP-FPM) + Composer
- MongoDB 6
Preparing Docker image with PHP + Composer + packages for MongoDB
You need to create a Dockerfile in the project directory
Dockerfile
FROM php:8.2-fpm
RUN apt-get -y update \
&& apt-get install -y libssl-dev pkg-config libzip-dev unzip git
RUN pecl install zlib zip mongodb \
&& docker-php-ext-enable zip \
&& docker-php-ext-enable mongodb
# Install composer (updated via entry point)
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
Run Image build from Dockerfile
docker build -t php8.2-fpm-mongo .
After completing the build, this Image can be used in the docker-compose.yml file, there will already be Composer and the libraries needed to run MongoDB.
Preparing Docker-compose with Nginx + PHP
You need to create a docker-compose.yml file in the application directory.
docker-compose.yml
version: '3.9'
services:
web:
image: nginx:latest
ports:
- '80:80'
volumes:
- ./app:/var/www/html
- ./config/default.conf:/etc/nginx/conf.d/default.conf
php-fpm:
image: php8.2-fpm-mongo
volumes:
- ./app:/var/www/html
You also need to create a directory app/
and an index.php
file in it, which will be our application.
app/index.php
<?php
phpinfo();
exit;
You will also need to create a Nginx default.conf configuration file. I placed it in the config/ folder in the project directory
config/default.conf
server {
listen 80;
server_name localhost;
index index.php index.html;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
root /var/www/html;
rewrite ^/(.*)/$ /$1 permanent;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass php-fpm:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_buffering off;
}
}
Structure of files and folders
.
├── app
│ └── index.php
├── config
│ └── default.conf
├── Dockerfile
└── docker-compose.yml
Checking Nginx + PHP
Run docker-compose
docker-compose up -d
Open localhost
in the browser.
If everything is correct, you should see phpinfo.
Installing PHP libraries into the project with Composer required by MongoDB
You need to create a composer.json
file in the app folder to install the packages and php extensions that are required for MongoDB.
app/composer.json
{
"require": {
"mongodb/mongodb": "^1.6",
"ext-mongodb": "^1.6"
}
}
To install packages you need to connect to the container with php-fpm:
docker exec -it [php-fpm-container] bash
The container name becomes known when you run docker-compose up -d
Once you are connected to the container, install composer packages with the command:
composer install
I think all went well and your project now has a vendor directory with installed packages and libraries for MongoDB
Adding MongoDB image to Docker-compose
You need to add the mongodb
service to the previously created docker-compose.yml
Stop launched containers with the command
docker-compose down
Add a new service to docker-compose.yml
mongodb:
image: "percona/percona-server-mongodb:6.0.4"
# image: "percona/percona-server-mongodb:6.0.4-3-arm64" # For Apple M1/M2
volumes:
- ./data:/data/db
restart: always
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: secret
MONGO_INITDB_DATABASE: tutorial
ports:
- "27017:27017"
I use Percona Server for MongoDB as a free open-source alternative to MongoDB.
You will also need to modify the php-fpm service a bit to include environment variables
php-fpm:
image: php8.2-fpm-mongo
volumes:
- ./app:/var/www/html
environment:
DB_USERNAME: root
DB_PASSWORD: secret
DB_HOST: mongodb # matches the service with mongodb
This way the final docker-compose.yml
will be
version: '3.9'
services:
web:
image: nginx:latest
ports:
- '80:80'
volumes:
- ./app:/var/www/html
- ./config/default.conf:/etc/nginx/conf.d/default.conf
php-fpm:
image: php8.2-fpm-mongo
volumes:
- ./app:/var/www/html
environment:
DB_USERNAME: root
DB_PASSWORD: secret
DB_HOST: mongodb # matches the service with mongodb
mongodb:
image: "percona/percona-server-mongodb:6.0.4"
# image: "percona/percona-server-mongodb:6.0.4-3-arm64" # For Apple Silicon M1/M2
volumes:
- ./data:/data/db
restart: always
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: secret
MONGO_INITDB_DATABASE: tutorial
ports:
- "27017:27017"
Run docker-compose
docker-compose up -d
Let's connect to MongoDB in a PHP application and write the test data
You need to modify the app/index.php
file
<?php
// Enabling Composer Packages
require __DIR__ . '/vendor/autoload.php';
// Get environment variables
$local_conf = getenv();
define('DB_USERNAME', $local_conf['DB_USERNAME']);
define('DB_PASSWORD', $local_conf['DB_PASSWORD']);
define('DB_HOST', $local_conf['DB_HOST']);
// Connect to MongoDB
$db_client = new \MongoDB\Client('mongodb://'. DB_USERNAME .':' . DB_PASSWORD . '@'. DB_HOST . ':27017/');
$db = $db_client->selectDatabase('tutorial');
// Create an index
$db->pages->createIndex(['page_id' => 1]);
// Test insert data
for ($page = 1; $page <= 1000; $page++) {
$data = [
'page_id' => $page,
'title' => "Page " . $page,
'date' => date("m.d.y H:i:s"),
'timestamp' => time(),
'mongodb_time' => new MongoDB\BSON\UTCDateTime(time() * 1000)
];
$updateResult = $db->pages->updateOne(
[
'page_id' => $page // query
],
['$set' => $data],
['upsert' => true]
);
echo $page . " " ;
}
echo '<br/>Finish';
exit;
This is a simple script that:
- Reads environment variables
- Connects to the database
- Creates Index by key
- Writes 1000 test documents in a loop.
You can run localhost
in your browser.
Checking database records with MongoDB Compass
Install MongoDB Compass, it's a great tool to check the results of your experiments.
Use localhost as host and user/pass from docker-compose.yml
Conclusion
The environment and an example of a minimal application are ready. It can be expanded and improved by adding logic and functions.
Suggestions and comments are welcome.
The project files and example code are available in the Github repository
In the next part, you will learn how to improve the script to make HTTP requests to the API using the GitHub API as an example. Link to next part
Top comments (2)
i receive this error in the end on my localhost
Fatal error: Uncaught MongoDB\Driver\Exception\ConnectionTimeoutException: No suitable servers found (
serverSelectionTryOnce
set): [Failed to resolve 'mongodb'] in /var/www/html/vendor/mongodb/mongodb/src/functions.php:565 Stack trace: #0 /var/www/html/vendor/mongodb/mongodb/src/functions.php(565): MongoDB\Driver\Manager->selectServer(Object(MongoDB\Driver\ReadPreference)) #1 /var/www/html/vendor/mongodb/mongodb/src/Collection.php(382): MongoDB\select_server(Object(MongoDB\Driver\Manager), Array) #2 /var/www/html/vendor/mongodb/mongodb/src/Collection.php(350): MongoDB\Collection->createIndexes(Array, Array) #3 /var/www/html/index.php(18): MongoDB\Collection->createIndex(Array) #4 {main} thrown in /var/www/html/vendor/mongodb/mongodb/src/functions.php on line 565That's weird,