4. Deploying PrestaShop From cPouta Server With Internal Docker Images
This guide shows how to deploy PrestaShop and MariaDB from private internal Docker images on a cPouta-hosted Kubernetes cluster using MicroK8s, and an Ingress with HTTPS.
Notes#
This guide uses private internal images from the ref-product-line-v1-2025 registry.
If these move to an “official" repository later, this guide must be updated.
TODO: Add persistence to PrestaShop
Introduction#
This document walks through deploying PrestaShop and MariaDB on a cPouta VM running MicroK8s.
The deployment uses:
- internal Docker images stored in GitLab Container Registry
- Kubernetes Docker registry secrets
- HTTPS-enabled Ingress (using cert-manager)
Prerequisites#
- Product Platform v2 documentation steps 1, 2 and 3 reviewed
- Internal PrestaShop & MariaDB images have been built in GitLab CI/CD
- cert-manager and nginx-ingress installed on MicroK8s (Platform v2 step 2)
Domain & registry secret#
Before deploying PrestaShop, make sure you have:
-
your cPouta VM domain
-
a gitlab-registry-secret for pulling private images
You can obtain your domain name and create the registry secret as described in the previous guide “3. Setting Up a Service”, so follow the same steps here without repeating them.
Creating and deploying YAML file#
Using these image:
-
PrestaShop Image:
-
MariaDB Image:
Create a prestashop-deplyoment.yaml
# MariaDB Service
---
apiVersion: v1
kind: Service
metadata:
name: prestashop-db
spec:
ports:
- port: 3306
selector:
app: prestashop-db
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: prestashop-db
spec:
replicas: 1
selector:
matchLabels:
app: prestashop-db
template:
metadata:
labels:
app: prestashop-db
spec:
containers:
- name: mariadb
image: gitlab.labranet.jamk.fi:4567/ref-product-line-v1-2025/ref-product-service-mysql-database-container-v1:latest
imagePullPolicy: "Always"
env:
- name: MYSQL_ROOT_PASSWORD
value: rootpassword
- name: MYSQL_DATABASE
value: prestashop
- name: MYSQL_USER
value: prestashop
- name: MYSQL_PASSWORD
value: password
imagePullSecrets:
- name: gitlab-registry-secret
# Prestashop Service
---
apiVersion: v1
kind: Service
metadata:
name: prestashop-service
spec:
selector:
app: prestashop
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: prestashop
spec:
replicas: 1
selector:
matchLabels:
app: prestashop
template:
metadata:
labels:
app: prestashop
spec:
containers:
- name: prestashop
image: gitlab.labranet.jamk.fi:4567/ref-product-line-v1-2025/ref-product-presta-shop-service-container-v1
imagePullPolicy: "Always"
ports:
- containerPort: 80
env:
- name: DB_SERVER
value: "prestashop-db"
- name: DB_USER
value: "prestashop"
- name: DB_PASSWD
value: "password"
- name: DB_NAME
value: "prestashop"
- name: PS_INSTALL_AUTO
value: "1"
- name: PS_DOMAIN
value: "<YOUR-DOMAIN-NAME>"
- name: PS_LANGUAGE
value: "fi"
- name: PS_FOLDER_ADMIN
value: "admin228" # Rename admin folder for security
- name: PS_ENABLE_SSL
value: "1"
- name: ADMIN_MAIL
value: "<EMAIL>"
- name: ADMIN_PASSWD
value: "password"
imagePullSecrets:
- name: gitlab-registry-secret
# Ingress
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: prestashop-ingress
spec:
ingressClassName: nginx
rules:
- host: "<YOUR-DOMAIN-NAME>"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: prestashop-service
port:
number: 80
- This will deploy PrestaShop as HTTP
Deploy PrestaShop from the server:
[rocky@rocky-vm ~]$ microk8s kubectl apply -f prestashop-deployment.yaml
service/prestashop-db created
deployment.apps/prestashop-db created
service/prestashop-service created
deployment.apps/prestashop created
ingress.networking.k8s.io/prestashop-ingress created
clusterissuer.cert-manager.io/letsencrypt-prod created
# See the status of the pods
[rocky@rocky-vm ~]$ microk8s kubectl get pods -w
NAME READY STATUS RESTARTS AGE
prestashop-6474ccfff9-68wdf 1/1 Running 0 15s
prestashop-db-7b54c8cdf-jtl6m 1/1 Running 0 15s
Note on HTTP Deployment:
When deploying PrestaShop as HTTP (as shown here), you might face some issues, particularly with the admin pages not loading properly or performing inconsistently. This could happen due to missing secure cookies, mixed content issues, or PrestaShop's expectation of SSL for certain features. If you encounter issues, consider deploying PrestaShop over HTTPS as outlined in the next section.
The deployment might take some time. After a while, you should be able to access your PrestaShop at the Domain you defined earlier.
Viewing installation logs:
[rocky@rocky-vm ~]$ microk8s kubectl logs -f prestashop-6474ccfff9-68wdf # <prestashop-pod-name>
# Shortened output
* Installing PrestaShop, this may take a while ...
* Launching the installer script...
-- Installation successful! --
* Removing install folder...
* No post-install script found, let's continue...
* Setup completed, removing lock file...
* Almost ! Starting web server now
* No init script found, let's continue...
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 10.1.248.117. Set the 'ServerName' directive globally to suppress this message
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 10.1.248.117. Set the 'ServerName' directive globally to suppress this message
[Fri Dec 05 09:51:12.261224 2025] [mpm_prefork:notice] [pid 1] AH00163: Apache/2.4.54 (Debian) configured -- resuming normal operations
[Fri Dec 05 09:51:12.261309 2025] [core:notice] [pid 1] AH00094: Command line: 'apache2 -D FOREGROUND'
Deploying PrestaShop as HTTPS#
To enable HTTPS, update your prestashop-deployment.yaml to include annotations and TLS settings in the Ingress configuration. Also, add the ClusterIssuer for Let's Encrypt at the end of the file.
# MariaDB Service
---
apiVersion: v1
kind: Service
metadata:
name: prestashop-db
spec:
ports:
- port: 3306
selector:
app: prestashop-db
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: prestashop-db
spec:
replicas: 1
selector:
matchLabels:
app: prestashop-db
template:
metadata:
labels:
app: prestashop-db
spec:
containers:
- name: mariadb
image: gitlab.labranet.jamk.fi:4567/ref-product-line-v1-2025/ref-product-service-mysql-database-container-v1:latest
imagePullPolicy: "Always"
env:
- name: MYSQL_ROOT_PASSWORD
value: rootpassword
- name: MYSQL_DATABASE
value: prestashop
- name: MYSQL_USER
value: prestashop
- name: MYSQL_PASSWORD
value: password
imagePullSecrets:
- name: gitlab-registry-secret
# Prestashop Service
---
apiVersion: v1
kind: Service
metadata:
name: prestashop-service
spec:
selector:
app: prestashop
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: prestashop
spec:
replicas: 1
selector:
matchLabels:
app: prestashop
template:
metadata:
labels:
app: prestashop
spec:
containers:
- name: prestashop
image: gitlab.labranet.jamk.fi:4567/ref-product-line-v1-2025/ref-product-presta-shop-service-container-v1
imagePullPolicy: "Always"
ports:
- containerPort: 80
env:
- name: DB_SERVER
value: "prestashop-db"
- name: DB_USER
value: "prestashop"
- name: DB_PASSWD
value: "password"
- name: DB_NAME
value: "prestashop"
- name: PS_INSTALL_AUTO
value: "1"
- name: PS_DOMAIN
value: "<YOUR-DOMAIN-NAME>"
- name: PS_LANGUAGE
value: "fi"
- name: PS_FOLDER_ADMIN
value: "admin228" # Rename admin folder for security
- name: PS_ENABLE_SSL
value: "1"
- name: ADMIN_MAIL
value: "<EMAIL>"
- name: ADMIN_PASSWD
value: "password"
imagePullSecrets:
- name: gitlab-registry-secret
# Ingress
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: prestashop-ingress
annotations: # Add these to enable HTTPS
cert-manager.io/cluster-issuer: "letsencrypt-prod" #
acme.cert-manager.io/http01-edit-in-place: "true" #
spec:
ingressClassName: nginx
tls:
- hosts:
- "<YOUR-DOMAIN-NAME>"
secretName: prestashop-tls
rules:
- host: "<YOUR-DOMAIN-NAME>"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: prestashop-service
port:
number: 80
# Add the ClusterIssuer to enable HTTPS
# ClusterIssuer (Let's Encrypt)
---
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: "<EMAIL>"
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- http01:
ingress:
class: nginx