docs/1.6/03-Tutorials/04-Cluster-Deployment/01-Digital-Ocean-(Docker-Machine).md
In this tutorial, you will learn how to create a Prisma cluster on Digital Ocean and deploy your Prisma services to it.
Digital Ocean is an easy-to-use provider of virtual servers. They offer configurable compute units of various sizes, called Droplets.
<InfoBox>The setup described in this section does not include features you would normally expect from production-ready servers, such as automated backups and active failover. We will add more guides in the future describing a more complete setup suitable for production use.
</InfoBox>The first thing you need to is install Docker and Docker Machine. The easiest way to install theses tools is by following the step in the Docker Docs directly.
<Instruction>Follow the instructions (steps 1 through 3) at https://docs.docker.com/machine/install-machine/#install-machine-directly to install Docker as well as Docker Machine.
</Instruction>Once you're done, you should be able to run the following command which will output the version of docker-machine:
docker-machine -v
If you haven't already, you need to start by creating an account at for Digital Ocean. You can do so here.
</Instruction>Once you have your account available, you need to generate a personal access token which is needed to create your Droplet.
<Instruction>Follow the instructions here to obtain your personal access token.
Make sure to save the token, you'll need it in the next step.
</Instruction>You can now go ahead and create your Droplet. The personal access token from the previous step will be used to associate the Droplet with your Digital Ocean account.
<Instruction>In your terminal, use docker-machine create to create your Droplet using the digitalocean driver. Note that you need to replace the __TOKEN__ placeholder with your personal access token from the previous step:
docker-machine create --driver digitalocean --digitalocean-access-token __TOKEN__ --digitalocean-size 1gb prisma
The --digitalocean-size 1gb argument indicates that the Droplet receives 1GB of memory. The last argument of the command, prisma, determines the name of the Droplet.
You will now have a running Droplet that can be controlled by docker-machine. You can list your current Droplets by running the following command:
docker-machine ls
Now that you have your Droplet up and running, you can install Prisma on it. As the Prisma infrastructure runs on Docker, you could theoretically do this by using the Docker CLI directly. In that case, you could use the Docker Compose file as foundation and run the required commands (e.g. docker-compose up) yourself.
However, the Prisma CLI actually offers some commands that you can use for convenience to not fiddle with Docker yourself. In this tutorial, you'll take advantage of these commands - under the hood they will simply configure your Docker environment and invoke the required CLI commands.
The docker CLI is a client that allows to create and manage your Docker containers on a dedicated host machine. By default, that host machine is your local machine (localhost). However, using docker-machine you can point the docker CLI to run against a different host. Meaning that all your docker commands (including docker-compose) can be executed to a remote machine over the internet.
So, the next step is to make sure your docker commands actually run against the remote Digital Ocean Droplet you just created. You can do so by setting a number of environment variables that'll be used by docker. But how do you know which environment variables - and what values to set? docker-machine to the rescue!
The following command prints the correct environment variables for you to set - in fact it even prints the commands that you need to execute in your terminal in order to set them correctly. Thank you docker-machine! š
docker-machine env prisma
The output of that command looks somewhat similar to the following (depending on your shell and OS the commands to set environment variables might differ):
$ docker-machine env prisma
export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://104.132.24.246:2376"
export DOCKER_CERT_PATH="/Users/johndoe/.docker/machine/machines/prisma"
export DOCKER_MACHINE_NAME="prisma"
# Run this command to configure your shell:
# eval $(docker-machine env prisma)
Copy the last line of that output, excluding the # in the beginning (which indicates a comment) and paste it into your terminal:
eval $(docker-machine env prisma)
That's it - all your docker (and therefore prisma local) commands will now run against the Digital Ocean Droplet instead of your local machine!
To actually install Prisma on your Droplet, you need to perform the following steps (we'll go over them in detail afterwards):
docker-compose.yml with proper configuration.env to configure the environment variables used by Dockerdocker-compose up to install Prisma on the DropletLet's get started!
<Instruction>First, go ahead and create a new directory on your file system where you'll place all the files for your project, you can call it digital-ocean-demo.
Inside that directory, create a new file called docker-compose.yml and copy the following contents into it:
version: "3"
services:
prisma-db:
image: mysql:5.7
container_name: prisma-db
networks:
- prisma
restart: always
command: mysqld --max-connections=1000 --sql-mode="ALLOW_INVALID_DATES,ANSI_QUOTES,ERROR_FOR_DIVISION_BY_ZERO,HIGH_NOT_PRECEDENCE,IGNORE_SPACE,NO_AUTO_CREATE_USER,NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,NO_DIR_IN_CREATE,NO_ENGINE_SUBSTITUTION,NO_FIELD_OPTIONS,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_UNSIGNED_SUBTRACTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,PIPES_AS_CONCAT,REAL_AS_FLOAT,STRICT_ALL_TABLES,STRICT_TRANS_TABLES,ANSI,DB2,MAXDB,MSSQL,MYSQL323,MYSQL40,ORACLE,POSTGRESQL,TRADITIONAL"
environment:
MYSQL_ROOT_PASSWORD: $SQL_INTERNAL_PASSWORD
MYSQL_DATABASE: $SQL_INTERNAL_DATABASE
ports:
- "3306:3306" # Temporary/debug mapping to the host
volumes:
- db-persistence:/var/lib/mysql
prisma-database:
image: prismagraphql/prisma:1.3
restart: always
ports:
- "0.0.0.0:${PORT}:${PORT}"
networks:
- prisma
environment:
PORT: $PORT
SQL_CLIENT_HOST_CLIENT1: $SQL_CLIENT_HOST
SQL_CLIENT_HOST_READONLY_CLIENT1: $SQL_CLIENT_HOST
SQL_CLIENT_HOST: $SQL_CLIENT_HOST
SQL_CLIENT_PORT: $SQL_CLIENT_PORT
SQL_CLIENT_USER: $SQL_CLIENT_USER
SQL_CLIENT_PASSWORD: $SQL_CLIENT_PASSWORD
SQL_CLIENT_CONNECTION_LIMIT: 10
SQL_INTERNAL_HOST: $SQL_INTERNAL_HOST
SQL_INTERNAL_PORT: $SQL_INTERNAL_PORT
SQL_INTERNAL_USER: $SQL_INTERNAL_USER
SQL_INTERNAL_PASSWORD: $SQL_INTERNAL_PASSWORD
SQL_INTERNAL_DATABASE: $SQL_INTERNAL_DATABASE
CLUSTER_ADDRESS: $CLUSTER_ADDRESS
SQL_INTERNAL_CONNECTION_LIMIT: 10
#CLUSTER_PUBLIC_KEY: $CLUSTER_PUBLIC_KEY
BUGSNAG_API_KEY: ""
ENABLE_METRICS: "0"
JAVA_OPTS: "-Xmx1G"
networks:
prisma:
driver: bridge
volumes:
db-persistence: ~
Note the comment in front of the environment.CLUSTER_PUBLIC_KEY property. For now, we don't provide a public key to the Prisma cluster which is going to enable everyone with access to the IP address of the Droplet to deploy and delete services to and from it! We'll add the security layer afterwards!
Next, create another file that you call .env. Then paste the following contents into it:
PORT=4466
CLUSTER_ADDRESS=http://prisma-database:${PORT}
SQL_CLIENT_HOST=prisma-db
SQL_CLIENT_PORT=3306
SQL_CLIENT_USER=root
SQL_CLIENT_PASSWORD=__SECRET_2__
SQL_CLIENT_CONNECTION_LIMIT=10
SQL_INTERNAL_HOST=prisma-db
SQL_INTERNAL_PORT=3306
SQL_INTERNAL_USER=root
SQL_INTERNAL_PASSWORD=__SECRET_2__
SQL_INTERNAL_DATABASE=graphcool
SQL_INTERNAL_CONNECTION_LIMIT=10
SCHEMA_MANAGER_SECRET=SECRET_1
SCHEMA_MANAGER_ENDPOINT=http://prisma-database:${PORT}/cluster/schema
Note: To learn more about the variables configured here, check the corresponding reference docs.
With these files in place, you can go ahead and install Prisma!
<Instruction>Inside the digital-ocean-demo directory, run the following command:
docker-compose up -d
Remember that thanks to Docker Machine, this command will now run against the remote host, i.e. your Digital Ocean Droplet. The -d option starts the container in detached mode, meaning it will run as a background process.
Awesome, you now have your Prisma cluster available on the Digital Ocean Droplet! This means you can add it as a new cluster to your cluster registry and then deploy your Prisma services to it!
The cluster registry is stored in ~/.prisma/config.yml. It lists all the clusters you can use to deploy your Prisma services (excluding the ones you configured through the Prisma Cloud).
There is two ways how you can a new cluster to the registry:
prisma cluster add command~/.prisma/config.yml and add the cluster manuallyIn both cases, there are three pieces of information that need to be provided:
environment.CLUSTER_PUBLIC_KEY variables. As noted above, we skipped that step for now but will come back to it in a bit to enable cluster security.You'll use the second option and add the cluster configuration to the registry manually.
<Instruction>Open ~/.prisma/config.yml and add a new entry (here called digital-ocean-cluster) to the clusters map:
clusters:
digital-ocean-cluster:
host: 'http://__DROPLET_IP_ADDRESS__:4466'
Notice that there currently is a placeholder of the IP address of the Digital Ocean Droplet, so the value for host is not yet valid!
There are several ways to figure out the IP of your Droplet, e.g. by checking the Digital Ocean Console. For this tutorial, you'll use the docker-machine CLI again.
In your terminal, run the following command:
docker-machine ip prisma
Note that prisma is just the name of the Droplet you initially created. This will print the IP address of that Droplet.
Copy the IP address that was printed from the command and use it to replace the __DROPLET_IP_ADDRESS__ placeholder in the URL that's the value for the host property of your digitical-ocean-cluster cluster in ~/.prisma/config.yml, e.g.:
host: 'http://104.131.127.241:4466'
You're now ready to deploy a Prisma service to the cluster.
<Instruction>Inside the digital-ocean-demo directory, run the following command:
prisma init hello-world
From the interactive prompt, choose the Minimal setup: database-only option.
This creates a new directory that has the initial setup for a minimal Prisma service:
hello-world
āāā .graphqlconfig.yml
āāā datamodel.graphql
āāā prisma.yml
Next, you can go ahead and deploy the Prisma service.
<Instruction>Navigate into the newly-created hello-world directory and deploy the service:
cd hello-world
prisma deploy
Because no cluster is specified in prisma.yml, the CLI now prompts you to select a cluster. The list includes the digital-ocean-cluster you previously added:
$ prisma deploy
? Please choose the cluster you want to deploy "hello-world@dev" to (Use arrow keys)
local Local cluster (requires Docker)
⯠digital-ocean-cluster Self-hosted
Select the digital-ocean-cluster from the list.
The CLI is now going to deploy the service to that cluster and write the cluster entry to prismal.yml.
The Prisma CLI in that case acts as a client for the Prisma Cluster API which is used to manage services on a specific cluster. If you want to explore that Cluster API yourself, you can navigate your browser to http://__DROPLET_IP_ADDRESS__:4466/cluster. Similar to before, you'll have to replace the __DROPLET_IP_ADDRESS__ placeholder with the actual IP address of your Digital Ocean Droplet.
This is it! Your Prisma service is now running on your local cluster and can be access through the endpoint that was printed by the prisma deploy command! It will look similar to this: http://__DROPLET_IP_ADDRESS__:4466/hello-world/dev.
You can go ahead and send the following mutation and query to it:
mutation {
createUser(data: {
name: "Sarah"
}) {
id
}
}
{
users {
id
name
}
}
As noted before, everyone with access to the endpoint of your cluster (http://__DROPLET_IP_ADDRESS__:4466/) will be able to access your cluster in any way they like. This means they can add new services or delete existing ones and also get full read/write-access to the application data from these services. This is a major security leak and should never be the case in any sort of production environment! Let's go and fix it.
Here's a quick overview of the steps you need to perform (like before, we'll go through each step in detail afterwards):
CLUSTER_PUBLIC_KEY environment variable to the Prisma cluster (this step enables the cluster authentication)clusterSecret to the cluster registryTo generate a public/private-keypair, you can use any mechanism you wish, e.g. the openssl CLI. For the purpose of this tutorial, you'll use the Prisma Cloud API.
Open https://api.cloud.prisma.sh/ in your browser and send the following query:
{
generateKeypair {
public
private
}
}
This query takes a few seconds and then returns a public and a private key.
<Instruction>From the response, copy the public key and add it as the CLUSTER_PUBLIC_KEY to your .env file:
CLUSTER_PUBLIC_KEY="-----BEGIN PUBLIC KEY-----\r\n [ long key omitted ] -----END PUBLIC KEY-----\r\n",
Next, you need to remove the comment in front of the environment.CLUSTER_PUBLIC_KEY property in docker-compose.yml:
# ... other properties
environment:
PORT: $PORT
SQL_CLIENT_HOST_CLIENT1: $SQL_CLIENT_HOST
SQL_CLIENT_HOST_READONLY_CLIENT1: $SQL_CLIENT_HOST
SQL_CLIENT_HOST: $SQL_CLIENT_HOST
SQL_CLIENT_PORT: $SQL_CLIENT_PORT
SQL_CLIENT_USER: $SQL_CLIENT_USER
SQL_CLIENT_PASSWORD: $SQL_CLIENT_PASSWORD
SQL_CLIENT_CONNECTION_LIMIT: 10
SQL_INTERNAL_HOST: $SQL_INTERNAL_HOST
SQL_INTERNAL_PORT: $SQL_INTERNAL_PORT
SQL_INTERNAL_USER: $SQL_INTERNAL_USER
SQL_INTERNAL_PASSWORD: $SQL_INTERNAL_PASSWORD
SQL_INTERNAL_DATABASE: $SQL_INTERNAL_DATABASE
CLUSTER_ADDRESS: $CLUSTER_ADDRESS
SQL_INTERNAL_CONNECTION_LIMIT: 10
CLUSTER_PUBLIC_KEY: $CLUSTER_PUBLIC_KEY # remove comment here
BUGSNAG_API_KEY: ""
ENABLE_METRICS: "0"
JAVA_OPTS: "-Xmx1G"
# ... other properties
Inside the digital-ocean-demo directory, run the following command to submit the new property along with its environment variable:
docker-compose up -d
Awesome - your cluster is now secured and only people who have access to your private key will be able to access it from now on!
Next, you need to make the private key available to the CLI so your prisma deploy and similar commands can be properly authenticated. The way to do this is by setting it as the clusterSecret in ~/.prisma/config.yml:
Open ~/.prisma/config.yml and paste the private key you received as the response from the previous generateKeypair query as the clusterSecret into it. The digital-ocean-cluster entry will then look similar to this:
clusters:
digital-ocean-cluster:
host: 'http://__DROPLET_IP_ADDRESS__:4466'
clusterSecret: "-----BEGIN RSA PRIVATE KEY-----\r\n[ long key omitted ]]\r\n-----END RSA PRIVATE KEY-----\r\n"
That's it - from now on all deploys to the cluster will be authenticated using the clusterSecret.