Getting Started on APPUiO Cloud with the Terminal using PHP
This tutorial explains how to run applications written in the PHP programming language on APPUiO Cloud using the command line.
If you aren’t familiar with issuing commands on a terminal session, you might want to try the Getting Started with PHP on the OpenShift Web Console guide instead.
Requirements
To follow this guide, please make sure that you have the following tools installed:
oc
-
You can download the OpenShift command directly from APPUiO Cloud, selecting the help menu (marked as a question mark) and selecting the "Command line tools" entry.
docker
orpodman
-
You can download them from www.docker.com and podman.io.
curl
-
Available from curl.se.
About the Application
To demo how to run applications written in the PHP programming language on APPUiO Cloud, we will use a small demo application using the Slim Framework, bundled as a container thanks to its corresponding Dockerfile
, and ready to be used on APPUiO Cloud.
You can browse the full source code of this application on GitLab.
The "Fortune in PHP" application does a few simple things:
-
When invoked on the browser, it returns a random number and a funny quote.
-
When invoked with an HTTP request including the
Accept: application/json
header, it returns the same information in JSON format. -
Finally, when invoked with an HTTP request including the
Accept: text/plain
header, it returns the same information in plain text format.
Learn more about the fortune-php
application, including how to edit and build it, on the project README.
The Application Router
The code below shows the main router of the application in the PHP programming language, located at public/index.php, courtesy of the Slim Framework.
$app->get('/', function (Request $request, Response $response, $args) use ($version, $hostname) {
$data = [
'message' => `fortune`,
'number' => rand(1, 1000),
'version' => $version,
'hostname' => $hostname
];
if ($request->hasHeader('Accept')) {
$acceptHeader = $request->getHeaderLine('Accept');
if ($acceptHeader === 'application/json') {
$json = json_encode($data);
$response->getBody()->write($json);
return $response->withHeader('Content-Type', 'application/json');
}
if ($acceptHeader === 'text/plain') {
$format = "Fortune %s cookie of the day #%d:\n\n%s";
$result = sprintf($format, $data['version'], $data['number'], $data['message']);
$response->getBody()->write($result);
return $response->withHeader('Content-Type', 'text/plain');
}
}
$view = Twig::fromRequest($request);
return $view->render($response, 'fortune.html', $data);
});
Run the Container
This step is optional; you can easily test the application locally with Docker:
docker run --rm --publish 8080:8080 registry.gitlab.com/vshn/applications/fortune-php:latest
Or with Podman:
podman run --rm --publish 8080:8080 registry.gitlab.com/vshn/applications/fortune-php:latest
Now you can test the application with curl
, for example to get some JSON:
curl http://localhost:8080 --header "Accept: application/json"
Or to see a plain text version:
curl http://localhost:8080 --header "Accept: text/plain"
You can also open a browser and navigate to localhost:8080 to get your fortune cookie of the day.
Dockerfile
The application includes a Dockerfile ready to build a container fully compatible with OpenShift. The snippet below shows the instructions used to build the actual running image:
# Step 2: Production image
# Adapted from
# https://github.com/TrafeX/docker-php-nginx
FROM alpine:3.17
WORKDIR /var/www/html
# Install packages and remove default server definition
RUN apk --no-cache add fortune nginx php81 php81-fpm php81-json supervisor
# Configure nginx
COPY config/nginx.conf /etc/nginx/nginx.conf
COPY config/conf.d /etc/nginx/conf.d/
# Configure PHP-FPM
COPY config/fpm-pool.conf /etc/php81/php-fpm.d/www.conf
COPY config/php.ini /etc/php81/conf.d/custom.ini
# Configure supervisord
COPY config/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
# Setup document root
RUN mkdir -p /var/www/html && mkdir -p /run/ && mkdir -p /var/cache/nginx
# The following lines make this image compatible with OpenShift.
# Source: https://torstenwalter.de/openshift/nginx/2017/08/04/nginx-on-openshift.html
RUN chmod g+rwx /var/cache/nginx /run /var/log/nginx
# Add application
COPY --chown=1001:0 templates /var/www/html/templates
COPY --chown=1001:0 public /var/www/html/public
COPY --from=composer --chown=1001:0 /app/vendor /var/www/html/vendor
# Make sure files/folders needed by the processes are accessable when they run under the 1001 user
RUN chown -R 1001:0 /var/www/html /run /var/lib/nginx /var/log/nginx
# Expose the port nginx is reachable on
EXPOSE 8080
# Switch to use a non-root user from here on
(1)
USER 1001:0
# Let supervisord start nginx & php-fpm
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]
1 | This explicitly prevents the container from running as root; this is a requirement of OpenShift, and a good practice for images in general. |
You can use the Dockerfile
above to build your own copy of the container, which you can then push to the registry of your choice. Clone the repo:
git clone https://gitlab.com/vshn/applications/fortune-php.git
cd
into it:
cd fortune-php
And build your image with Docker:
docker build -t fortune-php .
Or with Podman instead:
podman build -t fortune-php .
Step 1: Create a Project
Follow these steps to login to APPUiO Cloud on your terminal:
-
Login to the APPUiO Cloud console:
oc login --server=https://api.${zone}.appuio.cloud:6443
You can find the exact URL of your chosen zone in the APPUiO Cloud Portal.
This command displays a URL on your terminal:
You must obtain an API token by visiting https://oauth-openshift.apps.${zone}.appuio.cloud/oauth/token/request
-
Click on the link above and open it in your browser.
-
Click "Display token" and copy the login command shown as "Log in with this token"
-
Paste the
oc login
command on the terminal:oc login --token=sha256~_xxxxxx_xxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxxx-X \ --server=https://api.${zone}.appuio.cloud:6443
-
Create a new project called "[YOUR_USERNAME]-fortune-php"
oc new-project [YOUR_USERNAME]-fortune-php
-
To deploy the application we will use a standard Kubernetes
Deployment
object. Save the following YAML in a file calleddeployment.yaml
:apiVersion: apps/v1 kind: Deployment metadata: name: fortune-php spec: template: spec: containers: - image: registry.gitlab.com/vshn/applications/fortune-php:latest imagePullPolicy: Always name: fortune-container ports: - containerPort: 8080 metadata: labels: app: fortune-php selector: matchLabels: app: fortune-php strategy: type: Recreate --- apiVersion: v1 kind: Service metadata: name: fortune-php spec: ports: - port: 8080 targetPort: 8080 selector: app: fortune-php type: ClusterIP
-
Then apply the deployment to your APPUiO Cloud project:
oc apply -f deployment.yaml
And wait until your pod appears with the status "Running":
oc get pods --watch
Step 2: Publish your Application
At the moment your container is running but it’s not available from the Internet. To be able to access our application, we must create an Ingress
object.
-
Create another file called
ingress.yaml
with the following contents, customizing the parts marked as[YOUR_USERNAME]
and[YOUR_CHOSEN_ZONE]
to your liking (and according to the Zones documentation page):apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: cert-manager.io/cluster-issuer: letsencrypt-production name: fortune-php-ingress spec: rules: - host: [YOUR_USERNAME]-fortune-php.apps.[YOUR_CHOSEN_ZONE].appuio.cloud (1) http: paths: - pathType: Prefix path: / backend: service: name: fortune-php port: number: 8080 tls: - hosts: - [YOUR_USERNAME]-fortune-php.apps.[YOUR_CHOSEN_ZONE].appuio.cloud secretName: fortune-php-cert
1 Replace the placeholders YOUR_USERNAME
andYOUR_CHOSEN_ZONE
with valid values.
About URL lengths
Make sure that the total length of the prefix string
If your Ingress doesn’t generate a route after deploying your application, shorten the URL in your YAML and redeploy. |
-
Apply the ingress object to your APPUiO Cloud project and wait until you route shows as available.
oc apply -f ingress.yaml
And wait for your route to be ready:
oc get routes --watch
-
After a few seconds, you should be able to get your daily fortune message using
curl
in plain text!curl https://[YOUR_USERNAME]-fortune-php.apps.[YOUR_CHOSEN_ZONE].appuio.cloud --header "Accept: text/plain"
Or in JSON instead:
curl https://[YOUR_USERNAME]-fortune-php.apps.[YOUR_CHOSEN_ZONE].appuio.cloud --header "Accept: application/json"
Step 3: There’s no Step 3!
The "Fortune in PHP" application is now running on APPUiO Cloud. Congratulations! Hit the R key in your keyboard to see a new fortune message, or just wait 10 seconds to get a new one automatically.
What’s next? To run your own application written in PHP or using the Slim Framework on APPUiO Cloud, follow these steps:
-
Containerize the application making sure it’s compatible with APPUiO Cloud. The
Dockerfile
above can serve as a starting point. -
Enhance the deployment for your application with liveness and health probes, or better yet, create a Helm chart.
-
Configure your CI/CD system to automatically deploy your application to your preferred APPUiO Cloud zone.
Finally, when you’re done testing the fortune application, delete the fortune-php
project with the following command:
oc delete project [YOUR_USERNAME]-fortune-php