Skip to main content

Using Docker init to quickly dockerize your PHP application

Quickly dockerize your PHP application with Apache using the docker init command. This wizard-based tool generates the necessary Docker files and shows secure database integration.

· 6 min read
View raw
Christophe
Markdown, WSL and Docker lover ~ Insatiable curious.
Cet article existe aussi en français — lire la version française.

This article is over a year old but was reviewed on July 30, 2026 — the content is still accurate.

Using Docker init to quickly dockerize your PHP application

⚡
TL;DR

Learn how to quickly dockerize an existing PHP and Apache application using the docker init command. This guide walks you through the interactive wizard that automatically generates your Dockerfile, compose.yaml, and .dockerignore files. It demonstrates the process with a sample PHP script, shows how to run the newly containerized application, and explains the purpose of each generated file. The article also provides a tip on how to extend the configuration to securely add a database service using Docker Secrets.

How about asking Docker to create the files it needs itself?

If you're a regular reader of this blog, you'll know by now that you need a Dockerfile to describe how the Docker image should be created and what should be included in it, and very often you'll also need a compose.yaml file to explain how the container should be created, e.g. which port to map to, which volumes to use, and so on.

Imagine you've an existing PHP application and you don't want to create the files needed for the dockerization by hand.

You just want, very quickly and using a wizard, to be able to answer a few questions and hop, it's ready.

The docker init command is the one you're looking for. I had already given it a first try, back when PHP support had just landed, in Docker init now supports PHP; this article revisits it on a real application.

Get some scripts​

As an illustration, I'll use my aeSecure - QuickScan - Free viruses scanner project already introduced in my blog.

This is a Web application that scans files (a local website) for patterns that might indicate the presence of a virus.

So, to run aeSecure QuickScan, we need PHP and Apache.

Let's play...

First, we'll create a temporary folder and grab a copy of the script:

>user@machine: ~/yourproject

You've now a local version of the script. It's a single index.php script; nothing more at this stage.

Docker init​

Your values for this page
default
Applies to the commands on this pageSaved on this device only

Just start docker init in the console:

Starting docker init

As we can see, Docker init has already detected the presence of a PHP file so it's suggesting PHP with Apache. Great, just press Enter.

The next question will be about the version of PHP, type the one you wish (f.i. 8.2) and press Enter.

The third question will be about the relative path to use for the project. In our case, our PHP script is located in the root folder of our project (not in f.i./app) so just press Enter.

Now, you'll need to specify which port should be used for the application, I'll use the port 8080 but you can use the one you wish (as soon as not yet used).

And that's it.

Docker init has created our files

It's too simple, isn't it? Let's try the suggested commands and see if the site actually works.

First, create the container by running the docker compose up --build command then, once finished, just open your browser and surf to your local site (in my case http://localhost:8080) and ...

http://localhost:8080
The application is running

Let's take a look on created files​

.dockerignore​

The .dockerignore file specifies files and directories that should be excluded from Docker builds. So, when creating a Docker image you certainly don't want, for instance, the .git folder to be copied into the image. That folder (and many others) should stay on the computer.

By opening that file with a code editor, you'll then see that line:

**/.git

This is a gitignore file pattern that tells Git to ignore the `.git` directory and everything inside it everywhere in the repository. The `**` means 'at any nesting level' and `/.git` means 'the .git folder', so this prevents Git from trying to track its own internal folder.

Refer to https://docs.docker.com/go/build-context-dockerignore/ for more explanations.

compose.yaml​

Note

Previously, the file was named docker-compose.yaml (or docker-compose.yml).

The file will teach Docker how to make more than one container work together, f.i. our PHP application and a database service.

By opening the file, you'll see that right now, the only un-commented lines are those:

services:
server:
build:
context: .
ports:
- 8080:80

This is a Docker Compose configuration that defines a single service called 'server'. It builds a Docker image from the current directory and exposes port 8080 on your machine to port 80 inside the container, allowing you to access the containerized application through localhost:8080.

The rest is just for illustration.

Refer to https://docs.docker.com/go/compose-spec-reference/ for more explanation.

Dockerfile​

There are a lot of commented lines, if we look at un-commented ones, we can see this:

FROM php:8.2-apache
COPY . /var/www/html
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
USER www-data

This Dockerfile creates a Docker image based on PHP 8.2 with Apache web server, copies your application code into the web root directory, configures PHP to use production settings, and switches to running as the www-data user for security.

So, we'll use the PHP 8.2 Docker image shipped with apache in it (one image with both PHP and Apache).

We'll copy all files from our project (remember, our project is stored in folder /tmp/aesecure_quickscan) into the /var/www/html folder of the image. All files? No, that's incorrect. Remember the .dockerignore file: we'll copy all files that are not mentioned in .dockerignore.

Docker also takes care of renaming the standard php.ini-production file to php.ini.

The last command is to switch to the www-data user (so the container will not be running as root).

Refer to https://docs.docker.com/go/dockerfile-reference/ for more explanation.

README.Docker.md​

As a reminder of how to use your dockerized application, this file will give you the essential commands to run.

Generated files are yours​

The generated files won't be modified by Docker while you'll not run docker init again. This means you can make any changes you like to the files, but your changes won't be lost. It's a great way to quickly dockerize an application.

The example given in this blog post is a stand-alone project so docker init does all the magic. Assuming we'd needed a database, all we have to do is return to the compose.yaml file and un-comment the lines like below:

services:
server:
build:
context: .
ports:
- 8080:80
depends_on:
db:
condition: service_healthy
db:
image: postgres
restart: always
user: postgres
secrets:
- db-password
volumes:
- db-data:/var/lib/postgresql/data
environment:
- POSTGRES_DB=example
- POSTGRES_PASSWORD_FILE=/run/secrets/db-password
expose:
- 5432
healthcheck:
test: [ "CMD", "pg_isready" ]
interval: 10s
timeout: 5s
retries: 5
volumes:
db-data:
secrets:
db-password:
file: db/password.txt

This Docker Compose configuration defines two services: a web server that builds from the current directory and a PostgreSQL database. The server depends on the database being healthy before starting, and they communicate through defined ports and volumes. Sensitive database credentials are managed through Docker secrets rather than plain environment variables.

Docker secrets is used here

Hey! Did you see? Instead of hardcoding the password in the file, docker init has used a secret. This is smart.

Read my Docker secrets - Using your SSH key during the build process article if you don't know what is a secret

To make the example here above working, just create a folder called db with a file called password.txt there and paste your database password into it.

Of course, files generated by docker init are just skeletons: you can change what you want, so if you don't want to use secrets, no problem, you can hardcode the password; it's up to you.


Was this article helpful?
Did you try the steps in this article?