Verified Commit 30db2333 authored by Maarten de Waard's avatar Maarten de Waard
Browse files

Moved repository without moving history

# A Gitlab CI job template for building docker images using kaniko.
# Required environment variables:
# - KANIKO_BUILD_IMAGENAME: Build/target image name.
# Images will be named like
# ``
# , where TAG is the CI_COMMIT_REF_SLUG, and also the CI_COMMIT_TAG if set.
# Optional environment variables:
# - KANIKO_CONTEXT: The subdir which holds the Dockerfile, leave unset if
# the Dockerfile is located at root level of the project.
stage: build
# We need a shell to provide the registry credentials, so we need to use the
# kaniko debug image (
entrypoint: [""]
- echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json
- /kaniko/executor --cache=true --context ${CI_PROJECT_DIR}/${KANIKO_CONTEXT:-.} --dockerfile ${CI_PROJECT_DIR}/${KANIKO_CONTEXT:-.}/Dockerfile --destination ${CI_REGISTRY_IMAGE}/${KANIKO_BUILD_IMAGENAME}:${KANIKO_BUILD_TAGNAME}
- build
- tag
stage: build
KANIKO_BUILD_IMAGENAME: wordpress-cli-ansible
KANIKO_CONTEXT: wp-cli-docker
extends: .kaniko_build
- docker
# Run this job if files have changed that are used when building the docker
# image, or when the commit is a tag.
- changes:
- wp-cli-docker/**/**/*
- .gitlab-ci.yml
when: on_success
- if: '$CI_COMMIT_TAG'
when: on_success
stage: build
extends: .kaniko_build
- docker
# Run this job if files have changed that are used when building the docker
# image, or when the commit is a tag.
- changes:
- wp-docker/**
- .gitlab-ci.yml
when: on_success
- if: '$CI_COMMIT_TAG'
when: on_success
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
# Common VCS dirs
# Common backup files
# Various IDEs
apiVersion: v1
appVersion: "5.2.3"
description: WordPress with a replicated MariaDB backend
name: wordpress
# Please only change the chart version as part of the release procedure: see
version: 0.1.1
Apache License
Version 2.0, January 2004
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
implied, including, without limitation, any warranties or conditions
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2019 open
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
See the License for the specific language governing permissions and
limitations under the License.
## Setup
### Prerequisites
1. Make sure you have `kubernetes-cli` and `helm` (version >= 3) installed on
your development machine
2. Make sure you have a running kubernetes cluster that your kubectl is
connected to. Check this by running `kubectl version`. It should tell you the
client and server version of Kubernetes.
4. The redis and MariaDB helm charts live in a custom Bitnami chart repository
(the ones in the helm stable repository are deprecated and moved there). Get
the repository by running:
$ helm repo add bitnami
### Start WordPress on Kubernetes
#### Configuration
Copy `values-local.yaml.example` to `values-local.yaml`. This file contains a
lot of variables that you can change to adjust the WordPress installation to
your needs.
For a simple WordPress installation, you only need to edit the following values:
| Parameter | Description | Default |
| `ansibleVars.WP_URL` | The URL of your WordPress website | http://localhost |
| `ansibleVars.WP_TITLE` | The title of the site | Demo WP |
| `ansibleVars.WP_THEME` | A *slug* for the theme you want to install on your site (can also be changed through interface) | twentytwenty |
| `ansibleVars.WP_EMAIL` | The administrator's email adress | |
| `database.db.user` | Database user | wordpress |
| `database.db.password` | `wordpress` db user password | You **really** need to set this |
| `database.db.rootUser.password ` | root user password | You **really** need to set this |
| `database.db.replicationUser.password`| replication user password | You **really** need to set this |
You can read the descriptions of the other variables in
`values-local.yaml.example` and of even more variables in `values.yaml`.
##### Note about theme fallback
If there is no theme available to activate in wp_content then the fallback theme will be used
This is set by from values.yaml
##### Note about the `ansibleVars`:
All the variables under `ansibleVars` are used by the ansible playbook that is
run in the init container to configure the WordPress website. You can find their
default values in the `values.yaml` file. You can override single values of
`ansibleVars.<any variable>` in your `values-local.yaml` file. __NOTE__: if you
would want to override variables in `ansibleSecrets`, you have to copy the whole
`ansibleSecrets` string to `values-local.yaml`!
#### Installation
1. Install the helm dependencies by typing `helm dep update`
2. Start WordPress by typing running ``.
__NOTE__: if you override the image or initImage tags in values.yaml,
installation with this script ignores that.
See [What happens when I install this?](#what-happens-when-i-install-this) for
information on what happens now.
#### Removal
To undo an installation and remove all traces of it ever existing, use the
`` script. __NOTE__: use this at your own risk! Your databases, uploads, etc. will be removed for ever!
## Troubleshooting
To debug the **init** container, you can use `kubectl logs`, but because it is
not the default container, you need to use the `-c` argument as follows:
$ kubectl logs <pod> -c init-wordpress
## What happens when I install this?
### Installed pods
Helm will set up the kubernetes pods that are needed to run your website:
1. A WordPress pod that serves the site
2. Two MariaDB pods running the database (master-slave setup by default, unless
you changed this in `values-local.yaml`)
3. If you configured Redis, a Redis pod is also set up
The MariaDB and Redis pods are documented in the official [helm charts
repository](, this file documents the WordPress
pod that will serve the site.
### Init container
This chart provides an "init container" for the WordPress pod. This container
sets up the wordpress. Each time a pod is (re)started, the init container:
1. Downloads WordPress to a temporary directory
2. Configures that fresh WordPress
3. Downloads and activates the plugins specified in
### WordPress setup
After the init container is done, persistent volumes are mounted:
- `wpContentDir` contains the `wp-content` directory and is persistent over pod
- `wpUploadDir` contains the `uploads` directory that is usually a subdirectory
of the `wp-content` dir and is persistent.
- A configmap containing the `.htaccess` file for the uploads dir is mounted in
## Importing an existing WordPress site
We assume you have:
- A running kubernetes cluster
- `kubectl` installed on your machine and configured to connect to your running
- `tar` installed
- A database dump of your old website's database called `dump.sql`.
- The contents of the `wp-content` folder (usually at
`/var/www/html/wp-content`) in a local directory called `wp-content`.
Make sure the copy of the wp-content directory and the database dump are made at
the same time.
We will go through the following steps:
1. Set up a new WordPress site by installing this chart
2. Import the Database
3. Import the files from wp-content
### Set up a new WordPress site
Follow the instructions under [Start WordPress on
You might have to edit the following variables to reflect your current site's:
- Set `DB_PREFIX` to the database prefix that your current WordPress uses
- Set `WP_VERSION` to the version of your current WordPress site.
- Check if your current WordPress uses Redis. This is usually the case when you
have the `wp-redis` plugin installed. If so, enable redis in your
`values-local.yaml` by setting `redis.enabled` to `true`.
After installing, check if your site is available at the URL you specified in
`values-local.yaml`. When it is, type `helm ls` to find the name of your
deployment. In the rest of this document we will assume that your WordPress
deployment is named `wordpress-master`.
### Import the database
Make sure to remove all explicit URLs to your site from the database. If you
host your site on ``, WordPress tends to put links in the database as
`<link to your post>` or `<link to your
post>`. If you want to try this new deployment on a different domain, that will
not work. To fix this, search for `` in your database and
remove it. Repeat this step for ``.
When your database file is ready, import it with the following command:
$ kubectl exec -i wordpress-master-mariadb-master-0 -- mysql -uwordpress -p<your password> --database=wordpress_db < dump.sql
A breakup of the command:
- `kubectl exec` means you want to execute a command in a container
- `-i` makes sure that `stdin` is passed to the container. This means that we
can use `< dump.sql` to import the database export from your local system.
- We assume your database is running in a pod named
- `--` tells kubectl to stop interpreting command line arguments as kubectl
- `mysql` executes the `mysql` command in the container, with the following
- `-uwordpress` sets the MySQL user to wordpress
- `-p` provides the prassword of the `wordpress` user
- `--database=wordpress_db` selects the `wordpress_db` database.
- `< dump.sql` reads the file `dump.sql` and inserts it into the mysql command.
Change this if your MySQL database dump has a different filename.
### Import the files from wp-content/uploads
Similar to how you would normally use `scp` to copy files to a server, you can
use `kubectl cp` to copy files to your wordpress pod. Make sure that you copy
your uploads directory contents to the directory you have configured as the
`wpUploadDir` in the `values-local.yaml`. If you haven't configured it, it
defaults to `/var/www/wp-uploads-mount`. Also make sure it does not contain a
`.htaccess` file because that is provided by this chart.
run `kubectl get pods` to figure out what the name is of the pod running
$ kubectl get pods
wordpress-master-0 1/1 Running 0 20d
wordpress-master-mariadb-master-0 1/1 Running 9 20d
wordpress-master-mariadb-slave-0 1/1 Running 12 20d
In this case, we have 2 mariadb pods and one WordPress pod. We can copy the
wp-content contents to the pod with the following command:
$ kubectl cp uploads/ wordpress-master-0:/var/www/wp-uploads-mount
You'll have to change the ownership of the files to the `www-data` user:
$ kubectl exec -it wordpress-master-0 -- chown -R www-data:www-data /var/www/wp-uploads-mount
Note: this will say
`chown: changing ownership of '/var/www/wp-uploads-mount/.htaccess': Read-only file system`.
Don't worry, that's the mounted `.htaccess` file. All the other files' ownership *will* have changed.
## Known issues
The logs of your init container will contain the following warning:
TASK [wordpress-init : Add uploads symlink] ************************************
changed: [localhost]
[WARNING]: Cannot set fs attributes on a non-existent symlink target. follow
should be set to False to avoid this.
This is not a problem. This happens because the wp-uploads directory is
intentionally not mounted to the init container so a new WordPress can be
initialised while an old one is still running.
## Attribution
Most of this helm chart was made by following
## Release procedure
When releasing a new version of the wordpress-helm chart, please remember to do
the following:
* change the chart version in `Chart.yaml`;
* change the default `image.tag` and `initImage.tag` in `values.yaml` to the new
version (e.g., "0.1.2");
* create a git tag for the new version (e.g., "0.1.2") and push it to Gitlab
(any branch will do); the CI will create and push docker images tagged by that
same version string.
(You can push all git tags using `git push --tags`, or this specific one using
`git push origin 0.1.2`.)
set -v
# Upgrade or install application using the current git branch as docker tag
helm delete $releaseName
## Delete remaining PVCs:
kubectl delete pvc data-$releaseName-mariadb-master-0 data-$releaseName-mariadb-slave-0 data-$releaseName-database-0 redis-data-$releaseName-redis-master-0
# Use this installation script as an example for easy installation. Copy it to
# `` and edit the values file names if you need to.
set -v
# Makes sure you use docker image tags for the branch you're working on now
# Upgrade or install application using the current git branch as docker tag
helm upgrade $releaseName . --install -f values-local.yaml --set initImage.tag=$dockerTag --set image.tag=$dockerTag
- name: mariadb
version: 7.3.16
repository: "@bitnami"
- mysql
alias: database
- name: redis
version: 10.5.14
repository: "@bitnami"
condition: redis.enabled
- redis
1. Get the application URL by running these commands:
{{- if .Values.ingress.enabled }}
{{- range .Values.ingress.hosts }}
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ . }}{{ $.Values.ingress.path }}
{{- end }}
{{- else if contains "NodePort" .Values.service.type }}
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "wordpress.fullname" . }})
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT
{{- else if contains "LoadBalancer" .Values.service.type }}
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
You can watch the status of by running 'kubectl get svc -w {{ include "wordpress.fullname" . }}'
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "wordpress.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
echo http://$SERVICE_IP:{{ .Values.service.port }}
{{- else if contains "ClusterIP" .Values.service.type }}
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ include "" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0]}")
echo "Visit to use your application"
kubectl port-forward $POD_NAME 8080:80
{{- end }}
{{/* vim: set filetype=mustache: */}}
Expand the name of the chart.
{{- define "" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.