Skip to main content

Deploying apps

Deploying public apps

By default, all apps you deploy on Cloud Foundry are publicly accessible to everyone through the internet.

The cf push command can both create a new app and push a new version of an existing app.

  1. Put your app’s code and configuration files in a local directory.

  2. Target the appropriate organisation and space by running:

    cf target -o ORG_NAME -s SPACE_NAME
    

    where ORG_NAME is the name of the org, and SPACE_NAME is the name of the space.

  3. Create a manifest.yml file in the same local directory as your app’s code. The manifest file tells Cloud Foundry what to do with your app. An example manifest:

    ---
    applications:
    - name: APP_NAME
    

    where APP_NAME is the unique name for your app. You can run cf apps to see apps which already exist.

  4. Deploy your app by running the following in the directory which contains your app’s code, configuration files, and manifest:

    cf push
    

Your app should now be live at your app domain.

Refer to the Cloud Foundry documentation on deploying with app manifests for more information on the options available when you deploy an app.

Refer to the documentation on deploying an app to production if your app is a production app.

Set a target

To deploy an app, you need to set a target. A target is a combination of an org and a space.

Run the following to set the target:

cf target -o ORG_NAME -s SPACE_NAME

where ORG_NAME is the name of the org, and SPACE_NAME is the name of the space.

The Cloud Foundry client remembers the target until you change it.

You can change space without changing org by running:

cf target -s SPACE_NAME

You should target the sandbox space while you are testing your app. You can do this by running:

cf target -s sandbox

You will not normally need to target the sandbox space if you are a new user, as this space is the default for new users.

A possible exception to this is if your org is mature and has pre-existing spaces; you should check to ensure that you target the appropriate space for testing.

Caveats

  • Your app should not write to local storage. Cloud Foundry local storage is ephemeral and can be deleted at any time.
  • You may need to set environment variables for your app to work. All configuration information should be stored in environment variables, not in the code.
  • Instances will be restarted if they exceed memory limits.
  • Your application should write all its log messages to STDOUT/STDERR, rather than a log file.

Deploying private apps

By default, all apps you deploy on Cloud Foundry are publicly accessible to everyone through the internet.

If you need to restrict access to a public app, for example to implement basic authentication, you should refer to the documentation on route services.

If you do not want your apps to be publicly accessible at all, you must deploy your apps on the apps.internal domain. A common use case for this is that you have multiple micro-services that make up an overall app, and those micro-services must only be accessible by other micro-services in the app.

Private apps can communicate over any TCP-based protocol. If you wish to use TLS, you are responsible for the keys, certificates, protocol versions, and ciphers involved.

The following use case is that you have 2 apps to deploy:

  • a public app for your end users to interact with
  • a private app that the public app can securely connect to, but which is not accessible from the internet

To achieve this, you must:

Specify a private route in the private app’s manifest

Cloud Foundry uses routes to send requests to apps.

You must specify a private route in the private app’s manifest to tell Cloud Foundry that this app should not be accessible from the internet.

Create the private app’s manifest.yml with the following code:

---
applications:
- name: PRIVATE_APPNAME
  routes:
  - route: PRIVATE_APPNAME.apps.internal

If the private app was previously a public app, you must also run the following in the command line to remove the pre-existing public route:

cf unmap-route PRIVATE_APPNAME DOMAIN --hostname HOSTNAME

Refer to the Cloud Foundry documentation on routes for more information.

Set the private app URL in the public app’s manifest

The public app must read the private app URL from an environment variable in the public app’s manifest.

You must set:

  • the private app URL as a non-secure http URL
  • the domain as apps.internal
  • the URL as port 8080

To do this, create the public app’s manifest.yml with the following code:

---
applications:
- name: PUBLIC_APPNAME
  env:
    ENVIRONMENT_VARIABLE_NAME: http://PRIVATE_APPNAME.apps.internal:8080

where:

  • PUBLIC_APPNAME is the name of your public app
  • ENVIRONMENT_VARIABLE_NAME is the environment variable your public app reads (for example PRIVATE_APP_URL)
  • PRIVATE_APPNAME is the name of your private app

Create a network policy

By default, Cloud Foundry apps do not accept internal connections from other apps.

You must create a network policy to allow the public app to connect to the private app.

  1. Push both the public and private apps.
  2. Run the following in the command line to create the network policy:
cf add-network-policy PUBLIC_APPNAME PRIVATE_APPNAME --protocol tcp --port 8080
Warning If you are using Cloud Foundry CLI version 6 and the blue-green deploy plugin, you must recreate the network policy after each deployment

Data security classification

You can store data classified up to ‘official’ on the GOV.UK PaaS.

You cannot store data classified ‘secret‘ or ‘top secret‘ on the GOV.UK PaaS.

Refer to the information assurance page for information on the assurance process.

Learn about How GOV.UK PaaS meets the NCSC Cloud Security Principles.

Refer to the GOV.UK page on government security classifications for more information on these classifications.

Secure and non-secure requests

Requests could be made to an app’s public route over the non-secure http:// protocol due to:

  • misconfiguration of an app that allows non-encrypted traffic through
  • a service linking to the HTTP version of a page by mistake

Any requests made to a public app route over the http:// protocol will be automatically redirected to the base https:// version of that URL. The original query path and query parameters will be removed. This prevents a site from repeatedly redirecting back to the HTTP protocol without the user noticing.

Deploy an app to production

To deploy an app to a production environment, your department, agency or team must have a paid account with the GOV.UK PaaS.

Before you deploy an app to a production environment, you must set up a domain.

If you are a central government service using the GOV.UK domain, you must get a domain from GOV.UK for your service and set the DNS records required by your cdn-route service.

If you are using your own content distribution network (CDN), you must set up a domain by configuring your CDN.

You must also:

When you deploy an app to a production environment, you should:

Buildpacks

About buildpacks

Cloud Foundry uses buildpacks to provide runtime and framework support for applications in different languages (for example ensuring your app code has both the Ruby runtime and the Rails framework available to help it run). GOV.UK PaaS supports both standard and custom buildpacks:

  • standard buildpacks are buildpacks for common languages and frameworks that are supported by Cloud Foundry. You can check the installed buildpacks and their versions by running cf buildpacks.
  • custom buildpacks are developed by the wider community to enable hosting of applications in additional languages or frameworks
  • Docker images are a packaging format, and the requirements for the app and its runtime environment are the same as for apps deployed using buildpacks

Which buildpack should I use?

We recommend using the standard buildpacks to maximise the support you will receive from GOV.UK PaaS. Using a custom buildpack or Docker image will mean additional setup and maintenance costs.

Your responsibilities change depending on whether you use a standard buildpack, custom buildpack or a Docker image. Refer to the documentation on knowing your responsibilities for further information.

Buildpack language version updates

You should tell Cloud Foundry which version of your app’s language to use in the buildpack. You can specify an exact, minor or major version of the language. For example, with Python:

 
Category Python Example
Exact 3.5.2
Minor 3.5.x
Major 3.x
 

If you specify an exact version, you must update this version when the GOV.UK PaaS team update the language’s buildpack. Your app will fail to start if the language version it relies on is not supported by the latest language buildpack.

If you specify a major or a minor version, your app will automatically upgrade to use a more recent version of its language when the GOV.UK PaaS team updates the buildpack. The major or minor version must still be live for this upgrade to work. However, if there is a breaking change between language versions, your app may not behave as expected or even fail.

You should always check the GOV.UK PaaS announcements email for information on which language versions are in the latest language buildpacks.

How to use custom buildpacks

There are many application attribute options available when you push an app. You can use the buildpack attribute to specify a custom buildpack for your app through:

  • specifying the buildpack in the manifest.yml file
  • using the command line

Specifying buildpacks in the manifest file

You can set application attribute options in a manifest.yml file in the directory from which you are running the push command. This is done in one of three ways:

  1. By name: MY-BUILDPACK.
  2. By GitHub URL: https://github.com/cloudfoundry/java-buildpack.git.
  3. By GitHub URL with a branch or tag: https://github.com/cloudfoundry/java-buildpack.git#v3.3.0 for the v3.3.0 tag.
---
  ...
  buildpacks:
  - buildpack_URL

Command line options override the manifest; the option that overrides the custom buildpack attribute is -b.

Using the command line to choose buildpacks

Once a custom buildpack has been created, it can be pushed to either a public or private git repository. The repository URL can then be included in the command line to push your app.

If the repository is private, the push command must include https and username/password authentication

  • Public: $ cf push my-new-app -b git://github.com/johndoe/my-buildpack.git
  • Private: $ cf push my-new-app -b https://username:password@github.com/johndoe/my-buildpack.git

The app will then be deployed to Cloud Foundry, and the buildpack will be cloned from the repository and applied to the app.

If a buildpack is specified using cf push -b the detect step will be skipped and as a result, no buildpack detect scripts will be run.

Excluding files

Cloud Foundry is not version-control-aware, so cf push will deploy the working state of whatever files you have in that directory. In most cases, you will want to exclude files ignored by Git. From within your project directory, run

ln -s .gitignore .cfignore

and commit the .cfignore to your repository. However, read on if you have a more advanced CF setup.

A couple of important points on the .cfignore:

  1. if you have a more advanced app setup and have apps with a path other than the project root (where you run cf push from), you will need an additional .cfignore file located in each app path;

  2. also note that more advanced .gitignore syntax, such as the ** recursive subdirectory wildcard, are not supported by .cfignore.

Environment variables

You must store all configuration information for your app as environment variables.

This could include:

  • credentials for external services that your app uses, for example a Twitter account
  • values that will vary with each deployment of the app, for example the canonical URL

To view an app’s current environment variables, run cf env APP_NAME.

To create or update a variable, run the following:

cf set-env APP_NAME ENV_VAR_NAME ENV_VAR_VALUE

If you’re deploying a pre-existing app, you should check the app’s documentation for any environment variables you need to set.

For example, if the app has these instructions for deploying to Heroku:

heroku config:set VARIABLE=value

then you should run the equivalent command using cf set-env:

cf set-env APP_NAME VARIABLE value

System-provided environment variables

System-provided environment variables tell you about configuration details handled by the PaaS, for example:

  • the port on which the app is listening
  • the maximum memory each app instance can use
  • the external IP address of the app instance

Do not attempt to change the values of these system-provided variables using the command line or your app’s code.

VCAP_SERVICES and VCAP_APPLICATION are two important variables for initial setup:

  • VCAP_SERVICES contains details, including credentials, of any backing services bound to the app

  • VCAP_APPLICATION provides details of the currently running application, for example the language runtime version

To see the values of the system-provided variables, run cf env APP_NAME.

If your app connects to a backing service, you may need to have your app parse VCAP_SERVICES to get the credentials and other settings relating to that service and set the appropriate environment variables.

Some buildpacks will do this for you automatically. Refer to the deploy instructions for the language or framework you are using for more information.

Here is an example of the structure of the information contained in VCAP_SERVICES:

{
 "VCAP_SERVICES": {
  "postgres": [
   {
    "binding_name": null,
    "credentials": {
     "host": "rdsbroker-66ecd739-2e98-401a-9e45-15436165be06.c7uewwm9qebj.eu-west-1.rds.amazonaws.com",
     "jdbcuri": "jdbc:postgresql://rdsbroker-66ecd739-2e98-401a-9e45-17938165be06.c7uewwm9qebj.eu-west-1.rds.amazonaws.com:5432/DATABASE_NAME?password=PASSWORD\u0026ssl=true\u0026user=USERNAME",
     "name": "DATABASE_NAME",
     "password": "PASSWORD",
     "port": 5432,
     "uri": "postgres://USERNAME:PASSWORD@rdsbroker-66ecd739-2e98-401a-9e45-17938165be06.c7uewwm9qebj.eu-west-1.rds.amazonaws.com:5432/DATABASE_NAME",
     "username": "USERNAME"
    },
    "instance_name": "SERVICE_NAME",
    "label": "postgres",
    "name": "SERVICE_NAME",
    "plan": "PLAN",
    "provider": null,
    "syslog_drain_url": null,
    "tags": [
     "postgres",
     "relational"
    ],
    "volume_mounts": []
   }
  ]
 }
}

Refer to the Cloud Foundry documentation on environment variables for more information.

Names, routes and domains

App names and domain hostname clash

When you push an app, you have to assign an app name, either in the manifest or using the command line. The app name is also used as the default hostname of the app domain where the app will be hosted.

For example, if you push an app called myappin the London region, the PaaS tries to host it at myapp.london.cloudapps.digital. This is done using Cloud Foundry’s route functions.

The app domain is shared across all PaaS tenants within a region. in this example, if another tenant is using myapp.cloudapps.digital in the Ireland region, and you try to push an app called myapp to the same region, you will receive an error like this:

Using route myapp.london.cloudapps.digital
Binding myapp.london.cloudapps.digital to myapp...
FAILED
The route myapp.london.cloudapps.digital is already in use.

This will also happen if there is an app with the same name within your own organisation, but in a different space.

There are a few possible solutions to this problem:

  1. Minimise the chance of name clash by the way you name your apps; incorporate the name of your team, department or service to produce names that are unlikely to clash with other PaaS tenants. For example, if you work for the Ministry of Peace, instead of myapp, you could use minipeace-myapp.

    If you run different versions of an app in different spaces, you will also need to name them differently: for example, you might have minipeace-myapp-dev, minipeace-myapp-test, minipeace-myapp-production and so on.

  2. Manually specify a hostname that is different from the app name. You can do this as a command line option when you push:

    cf push myapp -n HOSTNAME

    or with a line in the app’s manifest.yml file:

    ---
        ...
        host: HOSTNAME
    

    You will still need to pick a hostname that is not in use.

    This solution means you can change the hostname while keeping the app name the same. This is more flexible, but means you need to keep track of both a hostname and an app name for each app. It could potentially make it easier to deploy to the wrong target.

  3. Use the random-route option. This appends a couple of random words to the hostname, to avoid clashes. For example, if your app is hosted in the London region and you run:

    cf push myapp --random-route

    the app will be hosted at something like https://myapp-mummifying-giraffe.london.cloudapps.digital.

    You can also specify this in your app’s manifest.yml file:

    random-route: true

    This is a convenient way to avoid clashes automatically. The disadvantage is that if your end users can see the resulting URLs, they may find the random words strange.

Custom domains

In production, you will probably want your app to be available through your own url (for example, yourapp.service.gov.uk). Refer to managing custom domains using the cdn-route service to see how to set this up.

Deploy a static HTML page

Refer to the Deploy a test static HTML section of the documentation.

Deploy a Ruby on Rails app

This section explains minimal steps for deploying a basic Rails app. Refer to the Cloud Foundry guide to deploying Ruby on Rails apps for more information.

If your app requires a backing service, it must be able to work with one of the services supported by PaaS. Instructions for deploying both backing service and non-backing service apps are given in this section.

These steps assume you have already carried out the setup process explained in the Get started section.

When you deploy an app, you must select a combination of an organisation and a space. This is called the target.

We have provided a sandbox space for you to use for learning about the PaaS. You may want to target the sandbox while you are testing by running:

cf target -s sandbox

It’s also important to realise that if you deploy an app using the same name and target as an existing app, the original will be replaced. If you are not sure about where to deploy your app, consult the rest of your team.

Deploying an app

To deploy a Rails app that does not require a backing service:

  1. Put the code for your Rails app into a local directory (for example, by checking it out of version control).

  2. Exclude files ignored by Git.

  3. If you’re using Rails 4, add the rails_12factor gem for better logging. Rails 5 has this functionality built in by default.

  4. Create a manifest.yml file in the folder where you checked out your app.

    ---
    applications:
    - name: my-rails-app
      memory: 256M
      buildpacks:
      - ruby_buildpack
    

    Replace my-rails-app with a unique name for your app. (You can use cf apps to see apps which already exist).

    The memory line tells the PaaS how much memory to allocate to the app.

    A buildpack provides any framework and runtime support required by an app. In this case, because the app is written in Ruby, you use the ruby_buildpack.

  5. Upload and start the application by running:

    cf push APPNAME
    

    from the directory which contains all the code and configuration files for your app.

    If you do not specify a name for the app after the cf push command, the name from the manifest file is used.

  6. Set any additional environment variables required by your app. For example:

    cf set-env APPNAME VARIABLE `value`
    

    where VARIABLE is a unique name for the variable, and value is the value to set.

Your app should now be available at your app domain.

For a production app, you should refer to the documentation on deploying an app to production.

Deploying with a PostgreSQL database

These instructions are for deploying a Rails app with a PostgreSQL database, and can be applied to other backing services. If you require more guidance on deploying an app with other supported backing services, contact us at gov-uk-paas-support@digital.cabinet-office.gov.uk.

The Cloud Foundry buildpack for Ruby automatically gets the details of the first available PostgreSQL service from the VCAP_SERVICES environment variable and sets the Ruby DATABASE_URL environment variable accordingly. Ensure that your app is configured to use DATABASE_URL to set its database configuration when deployed to the PaaS.

  1. Put the code for your Rails app into a local directory (for example, by checking it out of version control).

  2. If you are using Git, you may wish to exclude files ignored by Git.

  3. If you’re using Rails 4, add the rails_12factor gem for better logging. Rails 5 has this functionality built in by default.

  4. Create a manifest.yml file in the directory where you checked out your app.

    ---
    applications:
    - name: my-rails-app
      memory: 256M
      buildpacks:
      - ruby_buildpack
    

    Replace my-rails-app with a unique name for your app. (You can use cf apps to see apps which already exist).

    The memory line tells the PaaS how much memory to allocate to the app.

    A buildpack provides any framework and runtime support required by an app. In this case, because the app is written in Ruby, you use the ruby_buildpack.

  5. Upload the app without starting it using this command:

    cf push --no-start APPNAME
    

    from the directory which contains all the code and configuration files for your app.

    If you do not specify a name for the app after the cf push command, the name from the manifest file is used.

  6. Set any additional environment variables required by your app. For example:

    cf set-env APPNAME VARIABLE `value`
    

    where VARIABLE is a unique name for the variable, and value is the value to set.

  7. Create a PostgreSQL backing service (if required) and bind it to your app.

    To enable Rails support for database migrations, you may wish to create a Procfile in the same directory as your manifest.yml and Gemfile. The Procfile is a way to specify commands to be run when deploying your app.

    This is a minimal example of the Procfile content for Rails 5.0:

    web: rake db:migrate && bin/rails server
    
  8. Start your app by running:

    cf start APPNAME
    

Your app should now be available at your app domain.

For a production app, you should refer to the documentation on deploying an app to production.

Specify a Ruby version

You should tell Cloud Foundry which version of Ruby your app uses in the Ruby buildpack.

Refer to the documentation on buildpack language version updates for more information.

Refer to the Cloud Foundry documentation on specifying a Ruby version for more information.

Web servers

By default, the Cloud Foundry Ruby buildpack runs bin/rails server to spin up the application. In Rails 4 and below, this will use WEBrick as the web server. In Rails 5 and above, the default is puma.

You may want to use a different web server in production. See the Cloud Foundry documentation on configuring a production server for more information.

Troubleshooting asset precompilation

By default, the Rails buildpack performs asset precompilation during the staging phase. This is fine for most Rails apps, but it will not work for those which need to connect to services (such as the database) during asset compilation. (For an example, see MyUSA issue #636)

There are multiple potential solutions for this. Refer to the Cloud Foundry documentation on asset precompilation for more information.

Deploy a Node.js app

This section covers how to deploy a basic Node.js application to GOV.UK PaaS. Refer to the Cloud Foundry tips for Node.js applications for more information.

If your app requires a backing service, it must be able to work with one of the services supported by PaaS. Instructions for deploying both backing service and non-backing service apps are given in this section.

These instructions assume you have already carried out the setup process explained in the Get started section.

This is the code for the example app we are going to use. It is a basic web server that responds with a ‘Hello World’ message.

const http = require('http');

const port = process.env.PORT || 3000;

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello World\n');
});

server.listen(port, () => {
  console.log(`Server running on ${port}/`);
});
  1. Save the code to a new local directory as example.js.

  2. Add this manifest.yml file to the same directory:

    ---
    applications:
    - name: my-node-app
      command: node example.js
      memory: 256M
      buildpacks:
      - nodejs_buildpack
    

    Replace my-node-app with a unique name for your app. (You can use cf apps to see apps which already exist).

    The memory line tells the PaaS how much memory to allocate to the app.

    A buildpack provides any framework and runtime support required by an app. In this case, because the app is written in Node.js, you use the nodejs_buildpack.

  3. Include an npm package.json file to specify dependencies. The file should also specify a start command used to launch the app.

    This is a package.json file for our example app:

    {
      "name": "example",
      "version": "0.0.1",
      "author": "Demo",
      "engines": {
        "node": "6.11.x"
      }
    }
    

    The "engines" values specify the versions of Node.js and npm that the PaaS should use to run your app. Note that older versions may not be available: if your version is not supported, you will see an error message when you try to upload and start the app.

  4. You can optionally run npm install to preinstall dependencies rather than having them added during the PaaS staging process.

  5. Run cf push APPNAME from the top level of the directory which contains all the code and configuration files.

If you want to upload the app without starting it (for example, if you need to create a PostgreSQL service), run cf push --no-start APPNAME, then when you are ready to start the app, run cf start APPNAME.

Refer to the Cloud Foundry tips for Node.js applications for more information.

PostgreSQL setup with Node.js

These instructions are for deploying a Node.js app with a PostgreSQL database, and can be applied to other backing services. If you require more guidance on deploying an app with other supported backing services, contact us at gov-uk-paas-support@digital.cabinet-office.gov.uk.

If your app depends on a backing service such as PostgreSQL, it will need to parse the VCAP_SERVICES environment variable to get required details, such as service URLs and credentials.

You must create the service and bind it to your Node.js app as described in the PostgreSQL section.

You can use the cfenv module to assist with parsing the environment variables.

In your package.json file, you would specify cfenv as a dependency:

    {
      // ...
      "dependencies": {
        "cfenv": "*",
        // ...
      }
    }

Then in your app, you can get configuration information for backing services. This is an example of how to connect to a PostgreSQL service.

    var cfenv = require("cfenv");
    var pg = require('pg');
    var appEnv = cfenv.getAppEnv();
    var connectionString = appEnv.getServiceURL("SERVICE NAME");
    var client = new pg.Client({ connectionString, ssl: true });
    client.connect();

Replace “SERVICE NAME” in the above code with the exact name of the PostgreSQL service you created. The getServiceURL function returns a connection string which includes the username and password required to connect to the database.

Further information can be found in the:

You should also remember to include dependencies for any service bindings in package.json.

{
  // ...
  "dependencies": {
    "pg": "*",
    // ...
  }
}

Specify a Node.js version

You should tell Cloud Foundry which version of Node.js your app uses in the Node.js buildpack.

Refer to the documentation on buildpack language version updates for more information.

Refer to the Cloud Foundry documentation on specifying a Node.js version for more information.

Deploy a Django app

This section explains how to deploy an app using the Django framework. You may also need to refer to the Cloud Foundry documentation about the Python buildpack.

If your app requires a backing service, it must be able to work with one of the services supported by PaaS. Instructions for deploying both backing service and non-backing service apps are given in this section.

Before deploying a Django app, you must:

  1. Put the code for your Django app into a local directory (for example, by checking it out of version control).

  2. If you are using Git, add *.pyc and local_settings.py to your .gitignore file, then exclude files ignored by Git so Cloud Foundry will ignore them too.

  3. Run cf buildpacks in the command line to check the version of the Python buildpack.

  4. Go to the Python buildpack page on GitHub to check which versions of Python are currently included in the Python buildpack.

  5. Tell Cloud Foundry which version of Python to use by creating a runtime.txt file in the root of the local directory. This step is optional.

    Refer to the documentation on buildpack language version updates for more information.

    For more information, refer to the Cloud Foundry documentation on specifying a Python version.

  6. Make sure you have all the required modules for your project installed into your virtual environment (including Django).

  7. Generate a requirements.txt file if your project does not already have one by running pip freeze > requirements.txt in the root of the local folder.

    Add the following lines to the requirements.txt file:

    whitenoise==5.2.0  # manages static assets
    waitress==2.0.0    # a pure python WSGI server that is a replacement for gunicorn
    
  8. Tell Django to use whitenoise to serve static files. In settings.py within the project folder, add this line to MIDDLEWARE, immediately after middleware.security.SecurityMiddleware:

    'whitenoise.middleware.WhiteNoiseMiddleware',
    

    To serve the files so that they can be compressed and cached, add the following line to settings.py:

    STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
    

    See the whitenoise documentation for details.

  9. You should now tell Django where to look for static files. In settings.py within the project folder, add these lines below the import os statement.

    PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))
    
    STATIC_ROOT = os.path.join(PROJECT_ROOT, 'static')
    STATIC_URL = '/static/'
    

    In this case, the STATIC_ROOT variable tells Django to look for static files in a directory called static inside the project folder, and the STATIC_URL variable sets the path where those files will be served.

    You may need to alter these values depending on how static files are handled in your app.

    If your static files are located across multiple folders, you may need to use the STATICFILES_DIRS variable. See the Django documentation for full details on managing static files.

  10. Create a file called Procfile in the root of your local folder, and put in it:

        web: python manage.py migrate && waitress-serve --port=$PORT PROJECTNAME.wsgi:application
    

    The Procfile is a way to specify commands to be run when deploying your app; in this case, for database migration.

    PROJECTNAME should be replaced with whatever the name of your WSGI module is. By default, this is the same as the name of your project module, but it may be changed using the DJANGO_SETTINGS_MODULE environment variable. Using this configuration will automatically apply any database migrations.

  11. Create a manifest.yml file in the root of your local folder.

    ---
    applications:
    - name: my-app
      memory: 512M
      buildpacks:
      - python_buildpack
    

    where my-django-app is the name that will be used for the app within GOV.UK PaaS.

    Replace my-django-app with a unique name for your app. (You can use cf apps to see apps which already exist).

    The memory line tells the PaaS how much memory to allocate to the app.

  12. If your app requires a database, create a PostgreSQL backing service and bind it to your app. Then see the section on PostgreSQL setup below.

  13. To push your app, do:

    cf push APPNAME

    from the directory which contains all the code and configuration files.

    If you want to upload the app without starting it (for example, if you need to create a PostgreSQL service), run cf push --no-start APPNAME, then when you are ready to start the app, run cf start APPNAME.

You can now view your app at your app domain.

PostgreSQL setup with Django

These instructions are for deploying a Django app with a PostgreSQL database, and can be applied to other backing services. If you require more guidance on deploying an app with other supported backing services, contact us at gov-uk-paas-support@digital.cabinet-office.gov.uk.

Add these lines to your requirements.txt:

psycopg2==2.6.2 #installs the postgres driver
dj-database-url==0.3.0 #grabs environment variables and dumps them into a Django settings file

In your settings.py file, make sure you import the dj_database_url package we added to the requirements.txt file above:

    import dj_database_url

This package will automatically parse the VCAP_SERVICES environment variable and set DATABASE_URL to the first database found.

Then you’ll need to add a DATABASES setting. It’s best to add this to the settings.py file.

    DATABASES = {}
    DATABASES['default'] =  dj_database_url.config()

Your local_settings.py file will override this when you’re working locally.

The Procfile configuration provided in the section above will automatically apply database migrations.

Deploy a Java app

This section covers how to deploy a Java application to GOV.UK PaaS using the Java buildpack.

Deploying a JAR file

If your java application can be packaged as a self-executable JAR file then you can deploy it using cf push -p [your-app].jar [your-app-name].

This example will walk through creating a simple “Hello World” application that embeds the popular Jetty webserver. The instructions assume you have already carried out the setup process explained in the Get started section.

  1. Create a directory for your Java application:

    mkdir myapp
    cd myapp
    
  2. Download Jetty.

    curl -o ./jetty.jar http://central.maven.org/maven2/org/eclipse/jetty/aggregate/jetty-all/9.4.6.v20170531/jetty-all-9.4.6.v20170531-uber.jar
    

    This example uses version 9.4.6; check http://www.eclipse.org/jetty/download.html for the latest version of Jetty.

  3. Create a App.java file in your application directory. This class will serve as the entry point for your application:

    package app;
    
    import java.io.IOException;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import org.eclipse.jetty.server.Request;
    import org.eclipse.jetty.server.Server;
    import org.eclipse.jetty.server.handler.AbstractHandler;
    
    public class App extends AbstractHandler
    {
        @Override
        public void handle( String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response ) throws IOException, ServletException
        {
               response.setContentType("text/html; charset=utf-8");
               response.setStatus(HttpServletResponse.SC_OK);
               response.getWriter().println("<h1>Hello World</h1>");
               baseRequest.setHandled(true);
        }
    
        public static void main( String[] args ) throws Exception
        {
                int port = Integer.parseInt(System.getenv("PORT"));
                Server server = new Server(port);
                server.setHandler(new App());
    
                server.start();
                server.join();
        }
    }
    
  4. Compile your class:

    javac -d . -cp ./jetty.jar App.java
    
  5. Combine your class with Jetty to create an executable jar file:

    jar uvfe ./jetty.jar app.App app/App.class
    
  6. Push your jar file.

    cf push your-app-name -b java_buildpack -p ./jetty.jar
    

You have now deployed your Java application. Your application should now be accessible over HTTPS from the URL provided in the output.

If your application requires arguments in order to start, you can set the JBP_CONFIG_JAVA_MAIN environment variable. For example to add server and config.yml as arguments for your app, you could add the following to your application’s manifest.yml:

env:
  JBP_CONFIG_JAVA_MAIN: '{ arguments: "server config.yml" }

Deploying a WAR file

If your application can be packaged as a .war file you can deploy with the following:

cf push your-app-name -b java_buildpack -p your-app.war

If you need to use a specific version of Tomcat you can set the environment variable JBP_CONFIG_TOMCAT. For example to use Tomcat 8 you could add the following to your application’s manifest.yml:

env:
  JBP_CONFIG_TOMCAT: '{ tomcat: { version: 8.0.+ } }'

Note that you do not need to deploy Tomcat along with your application. The Java buildpack will run the servlet 2 and 3 web applications.

For more configuration options, refer to the Tomcat Container documentation.

Specify a Java version

You can specify the version of the Java Runtime Environment (JRE) by setting the environment variable JBP_CONFIG_OPEN_JDK_JRE in the application’s manifest.yml. For example, to use JRE 11:

  env:
    JBP_CONFIG_OPEN_JDK_JRE: '{ jre: { version: 11.+ } }'

The + in this example means it will use the latest point release available.

Deploying other JVM-based applications

The Java buildpack supports running any JVM-based applications (such as Scala or Clojure) with little or zero additional configuration. For more information, refer to the following examples of deploying applications using other frameworks and JVM-based languages:

Deploy a .NET Core app

This section covers how to deploy a .NET Core application to GOV.UK PaaS using the dotnet-core buildpack.

Deploying an ASP.NET Core Web App

This example will walk through creating a simple “Hello World” web application using the dotnet command line interface. The instructions assume you have already carried out the setup process explained in the Get started section.

  1. Install the dotnet core command line interface (CLI) tools

    See Microsoft’s documentation for instructions on how to do this.

  2. Create a new ASP.NET Core Web App using the dotnet CLI

    dotnet new webapp --name your-app-name
    
  3. Change directory into your new application’s directory

    cd your-app-name
    
  4. Create a manifest to describe how your application should be deployed

    ---
    applications:
    - name: your-app-name
      buildpacks:
      - dotnet_core_buildpack
      memory: 256M
    
  5. Pick a version of the .NET framework to target which is supported by the current buildpack

    1. Run cf buildpacks and look at the filename for dotnet_core_buildpack to work out the version (for example, if the filename was dotnet-core-buildpack-cflinuxfs3-v2.3.2.zip the version of the buildpack would be v2.3.2).
    2. Visit the buildpack’s releases page, for example https://github.com/cloudfoundry/dotnet-core-buildpack/releases/tag/v2.3.2
    3. Check the versions of dotnet-sdk supported by the buildpack - you should usually use the latest supported version, for example 3.0.100
    4. Edit your .csproj file and change the contents of the <TargetFramework> element to the target framework corresponding to the supported framework version (for example, use netcoreapp3.0 for a 3.0.x version of dotnet-sdk). See Microsoft’s documentation on supported target framework versions.
    5. Create a buildpack.yml file to specify which version of the framework the buildpack should use:

      ---
      dotnet-core:
        sdk: 3.x
      
  6. Push your application to GOV.UK PaaS

    cf push
    

You have now deployed your .NET core application. Your application should now be accessible over HTTPS from the URL provided in the output.

Stopping and starting apps

Run the following in the command line to temporarily stop your app and free up memory from your quota:

cf stop APP_NAME

Users visiting your app’s URL will get the error:

404 Not Found: Requested route ('APP_NAME.APP_DOMAIN') does not exist.

Databases and other provisioned services will still be running, and GOV.UK PaaS will charge you for any paid plans or services.

Run the following to restart a stopped app:

cf start APP_NAME

Deleting apps

Warning Deleting an app is irreversible.

You should run cf target to check which org and space you are in before you delete an app.

Run the following to delete an app:

cf delete APPNAME

Deleting app routes

Run the following to delete an app and that app’s routes at the same time, as long as those routes are not also mappped to other apps:

cf delete -r APPNAME

You can delete an app’s routes separately.

  1. Run cf routes to get a list of all active routes in the current space. This command will also list information about the routes, including hostname and app domain.

  2. Run the following to delete the app’s routes:

    cf delete-route DOMAIN_NAME --hostname HOSTNAME
    

Deleting a service instance

You must unbind a service instance from any apps it is bound to before you can delete that service instance. Note:

  • you do not need to delete an app’s service instances before you can delete that app
  • a service instance can be bound to more than one app
  1. Run cf services to see all service instances in your targeted space. Example output:

    name      service    plan    bound apps    last operation
    mystuff   postgres   small   my-app        create succeeded
    mydb      mysql      large   not-my-app    create succeeded
    
  2. Run the following to unbind a service instance:

    cf unbind-service APP_NAME SERVICE_NAME
    

    where:

- `APP_NAME` is the name of a deployed instance of your app exactly as specified in your manifest or push command
- `SERVICE_NAME` is a unique descriptive name for this service instance
  1. Run cf delete-service SERVICE_NAME to delete that service instance.

Deploy a Docker image

This section explains how to deploy an app from a Docker image. The role of the Docker image is to serve as a packaging format and the requirements for the app and its runtime environment are the same as for apps deployed using buildpacks. Configuration using manifest.yml also stays the same, albeit you should not specify buildpack. If you do, it will be ignored, which can create some confusion to anyone reading the manifest. Our platform currently supports deploying from the following:

Pushing local Docker images is not supported.

To deploy an app using a Docker image stored in Docker Hub using CF cli:

cf push myapp --docker-image dockerhuborg/app_image:tag

To deploy an app using a Docker image stored in Docker Trusted Registry (DTR) using CF cli:

cf push myapp --docker-image MY-PRIVATE-REGISTRY.DOMAIN:5000/image/name:tag

To deploy an app using a Docker image stored in a registry that requires authentication, follow the Cloud Foundry Docker image documentation instructions.

You might notice that the staging process is simplified when deploying from a Docker image - this is because there is no need to build the app from the pushed code using a buildpack. Also, the buildpack for apps deployed from a Docker image will be reported as unknown in the app information (cf app <myapp>).

There are a few more specifics about Docker image support in Cloud Foundry:

  • Local storage in each container instance is ephemeral. Every container launch will start with unmodified image.
  • Traffic will be routed to the lowest exposed port (by EXPOSE command in Dockerfile). The PORT environment variable will be also set to this number.
  • Buildpack based apps use bash to execute the app start command (bash -c <command>), but Docker image based apps use sh (sh -c <command>) - as bash presence cannot be assumed in your Docker image.
  • Privileged container mode is not supported. Features depending on this will not work.
  • Only registries that use Docker Registry API V2 are supported.
  • Images are cached based on tag. Using a tag like latest when doing quick iterations can result in errors. To prevent this, tags should be unique. For example, the time the image was created, or a git commit hash.

Your responsibilities change if you use a Docker image instead of a buildpack. Refer to the responsibility model guidance for further information.

Docker Registry Availability Requirements

Deploying, scaling, restarting or restaging an app using a Docker image are all dependent on the Docker registry being available, because these actions require pulling the image from the registry.

Note that Cloud Foundry can restart your application due to circumstances outside of your direct control, such as platform scaling or deployments, or failure of the underlying hardware platform.

If Cloud Foundry attempts to pull the image from the registry when the registry is not available, your application instance will fail to start, and you will receive a Failed to create container message. Once the Docker registry is available again, you will be able to re-deploy, restart or restage your app as required.

Applying security updates

When your app is built with a standard buildpack, you are responsible only for the code of your app. The platform provides both the buildpacks and also a safe and secure root filesystem (cflinuxfs3). Buildpack based apps never have root access in their container, which adds another layer of security. We do periodically apply security and functionality updates to the buildpacks, container root FS and the platform itself.

When your app is deployed from Docker image, responsibility for the root filesystem and for the complete build of your app shifts to you. You need to ensure proper measures are applied to make your app and root image safe and with the latest security updates. We recommend you use one of the major and well supported linux distributions as your base container. This way you will be able to build an image with latest security patches.