# Installing WoWonder or Sngine in Docker on Ubuntu
This guide walks through installing Docker, creating a clean container stack, preparing PHP and MariaDB, uploading either WoWonder or Sngine, and finishing the installation through the browser.
The goal is simple: keep the application isolated, keep the database separate, and avoid turning the server into a haunted house of mismatched PHP versions and mystery dependencies.
--------------------------------------------------
WHAT WE ARE BUILDING
--------------------------------------------------
The setup will use:
- Apache + PHP
- MariaDB
- Optional phpMyAdmin
- A dedicated Docker network
- Persistent database storage
- Persistent website files
Basic structure:
Internet
|
Domain / Reverse Proxy
|
Docker Network
|
+--- WoWonder or Sngine
|
+--- MariaDB
|
+--- Optional phpMyAdmin
Install one script per Docker stack.
Do not install both WoWonder and Sngine into the same document root unless you enjoy debugging software fistfights.
--------------------------------------------------
1. UPDATE UBUNTU
--------------------------------------------------
Update the server first:
sudo apt update && sudo apt upgrade -y
Install some basic tools:
sudo apt install ca-certificates curl unzip nano -y
--------------------------------------------------
2. REMOVE CONFLICTING DOCKER PACKAGES
--------------------------------------------------
If Ubuntu already has older Docker-related packages installed, remove them first:
sudo apt remove docker.io docker-compose docker-compose-v2 docker-doc docker-buildx podman-docker containerd runc -y
--------------------------------------------------
3. ADD DOCKER'S OFFICIAL REPOSITORY
--------------------------------------------------
Create the keyring directory:
sudo install -m 0755 -d /etc/apt/keyrings
Download Docker's signing key:
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
Make the key readable:
sudo chmod a+r /etc/apt/keyrings/docker.asc
Add Docker's repository:
sudo tee /etc/apt/sources.list.d/docker.sources > /dev/null <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF
Update the package list:
sudo apt update
Install Docker Engine and Docker Compose:
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y
--------------------------------------------------
4. VERIFY DOCKER
--------------------------------------------------
Check that Docker is running:
sudo systemctl status docker
Press q to exit the status screen.
Run Docker's test container:
sudo docker run hello-world
Enable Docker at boot:
sudo systemctl enable docker
--------------------------------------------------
5. CREATE THE PROJECT DIRECTORY
--------------------------------------------------
For WoWonder:
sudo mkdir -p /opt/wowonder/www
cd /opt/wowonder
For Sngine:
sudo mkdir -p /opt/sngine/www
cd /opt/sngine
Your project will eventually contain:
Dockerfile
docker-compose.yml
php.ini
www/
--------------------------------------------------
6. CREATE THE PHP DOCKERFILE
--------------------------------------------------
Create the file:
sudo nano Dockerfile
Paste:
FROM php:8.4-apache
RUN apt-get update && apt-get install -y \
libfreetype6-dev \
libjpeg62-turbo-dev \
libpng-dev \
libwebp-dev \
libzip-dev \
unzip \
curl \
&& docker-php-ext-configure gd \
--with-freetype \
--with-jpeg \
--with-webp \
&& docker-php-ext-install \
mysqli \
pdo \
pdo_mysql \
gd \
mbstring \
zip \
&& a2enmod rewrite headers expires \
&& sed -i '/<Directory \/var\/www\/>/,/<\/Directory>/ s/AllowOverride None/AllowOverride All/' \
/etc/apache2/apache2.conf
COPY php.ini /usr/local/etc/php/conf.d/custom.ini
WORKDIR /var/www/html
Save and exit.
--------------------------------------------------
7. CREATE php.ini
--------------------------------------------------
Create:
sudo nano php.ini
Paste:
memory_limit = 512M
upload_max_filesize = 256M
post_max_size = 256M
max_execution_time = 300
max_input_time = 300
max_input_vars = 5000
allow_url_fopen = On
file_uploads = On
date.timezone = America/New_York
display_errors = Off
log_errors = On
Change the timezone if needed.
--------------------------------------------------
8. CREATE docker-compose.yml
--------------------------------------------------
Create:
sudo nano docker-compose.yml
Paste:
services:
web:
build:
context: .
dockerfile: Dockerfile
container_name: social_web
restart: unless-stopped
ports:
- "8080:80"
volumes:
- ./www:/var/www/html
depends_on:
- database
networks:
- social_network
database:
image: mariadb:11
container_name: social_database
restart: unless-stopped
environment:
MARIADB_ROOT_PASSWORD: CHANGE_ROOT_PASSWORD
MARIADB_DATABASE: social_network
MARIADB_USER: social_user
MARIADB_PASSWORD: CHANGE_DATABASE_PASSWORD
volumes:
- database_data:/var/lib/mysql
networks:
- social_network
phpmyadmin:
image: phpmyadmin:latest
container_name: social_phpmyadmin
restart: unless-stopped
ports:
- "8081:80"
environment:
PMA_HOST: database
PMA_PORT: 3306
depends_on:
- database
networks:
- social_network
volumes:
database_data:
networks:
social_network:
--------------------------------------------------
9. SET STRONG DATABASE PASSWORDS
--------------------------------------------------
Replace:
CHANGE_ROOT_PASSWORD
and:
CHANGE_DATABASE_PASSWORD
with strong passwords.
Example:
MARIADB_ROOT_PASSWORD: 8gH9xZpV2uQm7K4w
MARIADB_DATABASE: social_network
MARIADB_USER: social_user
MARIADB_PASSWORD: G9m7Xv4pQ8rZ2nL6
Use your own passwords, not those examples.
--------------------------------------------------
10. BUILD THE CONTAINERS
--------------------------------------------------
Build the PHP image:
sudo docker compose build
Start the stack:
sudo docker compose up -d
Check container status:
sudo docker compose ps
You should see:
social_web
social_database
social_phpmyadmin
running.
--------------------------------------------------
11. TEST PHP
--------------------------------------------------
Create a temporary PHP info page:
sudo nano www/info.php
Paste:
<?php phpinfo();
Visit:
http://YOUR_SERVER_IP:8080/info.php
Confirm that PHP includes modules such as:
mysqli
pdo_mysql
mbstring
curl
gd
zip
openssl
fileinfo
Delete the test page when finished:
sudo rm www/info.php
Leaving phpinfo public is basically publishing your server's autobiography to strangers.
--------------------------------------------------
12. UPLOAD WOWONDER OR SNGINE
--------------------------------------------------
Upload the application files into the www directory.
For WoWonder:
/opt/wowonder/www
For Sngine:
/opt/sngine/www
You want the actual script files in the document root.
A typical structure may look like:
www/
├── index.php
├── assets/
├── includes/
├── admin/
├── install/
└── other application files
Do not upload the entire marketplace download package if the package contains documentation, licensing files, screenshots, and a separate Script folder.
Upload the actual script contents.
--------------------------------------------------
13. SET FILE OWNERSHIP AND PERMISSIONS
--------------------------------------------------
Set Apache ownership:
sudo chown -R 33:33 www
Set directory permissions:
sudo find www -type d -exec chmod 755 {} \;
Set file permissions:
sudo find www -type f -exec chmod 644 {} \;
Do not blindly use:
chmod -R 777
That fixes permissions the same way removing every lock in your house fixes lost-key problems.
--------------------------------------------------
14. INSTALL WOWONDER
--------------------------------------------------
Open the installer in your browser:
http://YOUR_SERVER_IP:8080/install
Use these database settings:
Database Host:
database
Database Name:
social_network
Database Username:
social_user
Database Password:
Use the password you placed in docker-compose.yml.
Do not use localhost.
The database runs in a separate container.
Inside Docker, the correct MariaDB hostname is:
database
because that is the Docker Compose service name.
--------------------------------------------------
15. INSTALL SNGINE
--------------------------------------------------
Open the Sngine installer URL in your browser.
Depending on the release, this may simply be:
Use the same database information:
Database Host:
database
Database Name:
social_network
Database Username:
social_user
Database Password:
Use your configured MariaDB user password.
Again, use:
database
not:
localhost
--------------------------------------------------
16. VERIFY PHP INSIDE THE CONTAINER
--------------------------------------------------
Check the PHP version:
sudo docker exec -it social_web php -v
Check loaded modules:
sudo docker exec -it social_web php -m
Look for:
curl
fileinfo
gd
mbstring
mysqli
openssl
pdo_mysql
zip
--------------------------------------------------
17. phpMyAdmin
--------------------------------------------------
During setup, phpMyAdmin will be available at:
Use:
Server:
database
Username:
social_user
Password:
Use your MariaDB user password.
You can also use the MariaDB root account if necessary.
For production, do not leave phpMyAdmin openly exposed unless you have a reason to.
--------------------------------------------------
18. CONNECT A REAL DOMAIN
--------------------------------------------------
Eventually you will probably want something like:
instead of:
The usual layout is:
Visitor
|
HTTPS Domain
|
Nginx / Apache / Hosting Panel
|
127.0.0.1:8080
|
Docker Web Container
Your reverse proxy sends traffic from the domain to:
127.0.0.1:8080
--------------------------------------------------
19. PRODUCTION PORT SETUP
--------------------------------------------------
Once the site is installed and working, it is safer to bind the web container only to localhost.
Change:
ports:
- "8080:80"
to:
ports:
- "127.0.0.1:8080:80"
This prevents the Docker web port from being directly exposed to the Internet.
--------------------------------------------------
20. DO NOT EXPOSE MARIADB PUBLICLY
--------------------------------------------------
The database service intentionally does not contain:
ports:
- "3306:3306"
That is good.
The application connects internally to:
database:3306
There is usually no reason for MariaDB to be directly reachable from the Internet.
--------------------------------------------------
21. REMOVE PUBLIC phpMyAdmin ACCESS
--------------------------------------------------
After installation, remove this section from phpMyAdmin if you no longer need direct browser access:
ports:
- "8081:80"
Then restart the stack:
sudo docker compose down
sudo docker compose up -d
phpMyAdmin can remain on the internal Docker network without being publicly exposed.
--------------------------------------------------
22. START THE STACK
--------------------------------------------------
sudo docker compose up -d
--------------------------------------------------
23. STOP THE STACK
--------------------------------------------------
sudo docker compose down
--------------------------------------------------
24. RESTART THE STACK
--------------------------------------------------
sudo docker compose restart
--------------------------------------------------
25. CHECK CONTAINER STATUS
--------------------------------------------------
sudo docker compose ps
--------------------------------------------------
26. VIEW APPLICATION LOGS
--------------------------------------------------
sudo docker logs social_web
Follow the log live:
sudo docker logs -f social_web
--------------------------------------------------
27. VIEW DATABASE LOGS
--------------------------------------------------
sudo docker logs social_database
--------------------------------------------------
28. ENTER THE WEB CONTAINER
--------------------------------------------------
Run:
sudo docker exec -it social_web bash
Useful commands inside the container:
php -v
php -m
Exit with:
exit
--------------------------------------------------
29. ENTER MARIADB
--------------------------------------------------
Run:
sudo docker exec -it social_database mariadb -u root -p
Enter the MariaDB root password.
Show databases:
SHOW DATABASES;
You should see:
social_network
Exit MariaDB:
exit;
--------------------------------------------------
30. BACKUP THE DATABASE
--------------------------------------------------
Create a database backup:
sudo docker exec social_database mariadb-dump -u root -pYOUR_ROOT_PASSWORD social_network > social_network_backup.sql
Restore it with:
cat social_network_backup.sql | sudo docker exec -i social_database mariadb -u root -pYOUR_ROOT_PASSWORD social_network
If you place the password directly after -p, there is no space between them.
For regular automated backups, use a safer credentials method so the password does not live in shell history.
--------------------------------------------------
31. BACKUP THE WEBSITE FILES
--------------------------------------------------
Create a compressed website backup:
sudo tar -czf website-backup.tar.gz www/
A complete backup requires both:
Website Files
+
Database
Backing up only one side of a database-driven site is roughly equivalent to backing up a car by photographing the steering wheel.
--------------------------------------------------
32. UPDATE DOCKER IMAGES
--------------------------------------------------
Pull updated container images:
sudo docker compose pull
Rebuild the PHP container:
sudo docker compose build --pull
Start the updated stack:
sudo docker compose up -d
--------------------------------------------------
33. UPDATE WOWONDER OR SNGINE
--------------------------------------------------
Updating the script itself is separate from updating Docker.
Before updating either application:
1. Back up the database.
2. Back up the website files.
3. Read the script developer's upgrade instructions.
4. Upload or apply the update.
5. Run any required database migration or upgrade URL.
6. Clear application caches if required.
7. Test the site.
Test at least:
- Login
- Registration
- Posting
- Uploads
- Messaging
- Notifications
- Cron jobs
- Admin panel
- Theme
- Plugins or custom modifications
Never assume an application update can simply overwrite everything.
Custom themes and modifications have a nasty habit of disappearing the second nobody makes a backup.
--------------------------------------------------
34. RECOMMENDED PRODUCTION docker-compose.yml
--------------------------------------------------
A cleaner production version looks like this:
services:
web:
build:
context: .
dockerfile: Dockerfile
container_name: social_web
restart: unless-stopped
ports:
- "127.0.0.1:8080:80"
volumes:
- ./www:/var/www/html
depends_on:
- database
networks:
- social_network
database:
image: mariadb:11
container_name: social_database
restart: unless-stopped
environment:
MARIADB_ROOT_PASSWORD: CHANGE_ROOT_PASSWORD
MARIADB_DATABASE: social_network
MARIADB_USER: social_user
MARIADB_PASSWORD: CHANGE_DATABASE_PASSWORD
volumes:
- database_data:/var/lib/mysql
networks:
- social_network
phpmyadmin:
image: phpmyadmin:latest
container_name: social_phpmyadmin
restart: unless-stopped
environment:
PMA_HOST: database
PMA_PORT: 3306
depends_on:
- database
networks:
- social_network
volumes:
database_data:
networks:
social_network:
Notice that phpMyAdmin has no public port.
MariaDB also has no public port.
The website listens only on:
127.0.0.1:8080
Your reverse proxy handles public HTTPS traffic.
--------------------------------------------------
35. RECOMMENDED FINAL ARCHITECTURE
--------------------------------------------------
A production setup should look something like this:
Cloudflare
|
Domain
|
Nginx / Apache Reverse Proxy
|
Docker Network
|
+--- WoWonder or Sngine
|
+--- MariaDB
|
+--- Optional phpMyAdmin
Keep public:
80
443
Keep private whenever possible:
3306
8080
8081
That gives you a cleaner installation, easier backups, easier migration, isolated dependencies, and far less server spaghetti when PHP, MariaDB, or some future update decides today is apparently chaos day.
pHiLdO The URL Shrink
[email protected]
https://phildo.xyz