How to Setup a Ghost Blog using Docker and DigitalOcean Spaces
This guide describes how you can setup an Ghost blog using Docker and DigitalOcean Spaces. Spaces will be used to store the images as well as being a CDN. This Ghost blog is running using the setup described below.
Requirements
- Get yourself a domain. You have to change to DigitalOcean's name servers. You can read more about how to change domain servers here
- Setup your VPS and install Docker and Docker Compose
- Setup DigitalOcean Spaces with your domain. You can read a setup guide for DigitalOcean Spaces here
Folder Structure
.dockerignore
.gitignore
docker-compose.yml
secrets.env
|-- ghost
|-- Dockerfile
Ghost Dockerfile
The Dockerfile for the Ghost blog image lies inside the ghost folder. The Dockerfile contains the following:
FROM ghost:2.25.1
WORKDIR /var/lib/ghost
RUN npm install ghost-storage-adapter-s3
RUN cp -vr ./node_modules/ghost-storage-adapter-s3 ./current/core/server/adapters/storage/digitalocean
The first line uses the Ghost Docker image version 2.25.1 as the base.
FROM ghost:2.25.1
In the second line we change the working directory to /var/lib/ghost
. This is because this the base location of the ghost installation of the Ghost Docker image.
WORKDIR /var/lib/ghost
Ghost blogs have support for custom storage adapters, or in other words we can use custom storage locations for our images. E.g Amazon S3, DigitalOcean spaces and so on. In this guide we will use DigitalOcean Spaces. We install a npm package called ghost-storage-adapter-s3
. This package is actually used for Amazon S3. However, DigitalOcean Spaces also have support for the S3 syntax.
RUN npm install ghost-storage-adapter-s3
Lastly, we have to copy the npm package into the folder for custom storage adapters which is located at current/core/server/adapters/storage/digitalocean
. The last part digitalocean
is a custom name for our storage adapter which can be changed, but you have to remember what your folder is called later.
RUN cp -vr ./node_modules/ghost-storage-adapter-s3 ./current/core/server/adapters/storage/digitalocean
Docker Compose
The complete docker-compose.yml
file is shown below
version: '3.1'
services:
ghost:
build: ghost
restart: always
expose:
- 2368:2368
depends_on:
- db
env_file:
- secrets.env
volumes:
- ~/data/ghost:/var/lib/ghost/content
db:
image: mysql:5.7
restart: always
env_file:
- secrets.env
volumes:
- ~/data/mysql:/var/lib/mysql
networks:
default:
external:
name: nginx-proxy
Ghost
The first line in the docker-compose file we set to build the local Dockerfile in the ghost folder
build: ghost
Then we set the image to always restart
restart: always
The image will be exposed on port 2368
expose:
- 2368:2368
The ghost image will depend on the db service, and the following line will make sure the db instance is started first
depends_on:
- db
The ghost configuration files is located in the folder /var/lib/ghost/content
. To save those files we have to expose the files through volumes. That will make the file persist through restarts of the images. We will make the ghost content files be available on the host in the folder ~/data/ghost
.
volumes:
- ~/data/ghost:/var/lib/ghost/content
Lastly, we add the secrets file. We don't want to have the secrets in the git repository so we add to the host file location. For this setup to work properly you need a specific set of variables in the secrets.env
. You can read more about the setup in the secrets section.
env_file:
- secrets.env
Database
The first line of the database service says that the MySQL 5.7 docker images should be used.
image: mysql:5.7
The second line tells the image to always restart
restart: always
Next we add the secrets file
env_file:
- secrets.env
Lastly we add the MySQL folder to volumes to make the data to persist through restarts of the image
volumes:
- ~/data/mysql:/var/lib/mysql
Secrets
For the setup to work you need the following variables in the secrets.env
file
Variabel name | Value |
---|---|
database__client | mysql |
database__connection__host | db |
database__connection__user | database_username |
database__connection__password | database_password |
database__connection__database | ghost |
MYSQL__ROOT__PASSWORD | database_password |
storage__active | digitalocean |
AWS_ACCESS_KEY_ID | spaces_access_key |
AWS_SECRET_ACCESS_KEY | spaces_access_secret |
AWS_DEFAULT_REGION | your_spaces_region_location |
GHOST_STORAGE_ADAPTER_S3_PATH_BUCKET | |
GHOST_STORAGE_ADAPTER_S3_ASSET_HOST | |
GHOST_STORAGE_ADAPTER_S3_ENDPOINT | |
GHOST_STORAGE_ADAPTER_S3_ACL | public-read |
The database__connection
variables is used by the ghost instance to connect to the database. These variables are self explanatory. You should change these variables to something different from the list above.
MYSQL__ROOT__PASSWORD
is used by the mysql image. The variable is used to set the root password for the database. This variable has to be the same as database__connection__password
storage__active
is the name of the custom storage adapter from earlier. In this case the folder name of the custom storage adapter is digitalocean
The AWS
variables is used by the custom NodeJS storage adapter. AWS_ACCESS_KEY_ID
and AWS_SECRET_ACCESS_KEY
you find in Digitaloceans developer console under the API tab. Click on Generate New Key
to generate a new pair of access key and secret keys. The key in DigitalOcean equals AWS_ACCESS_KEY_ID
and the secret equals AWS_SECRET_ACCESS_KEY
. Remember to note the secret as it will not be visible later.
AWS_DEFAULT_REGION
of the space you can find by clicking on the spaces tab. In the spaces list your space will have a link below the name. By looking at you see the region name. In the image below you can see that the AWS_DEFAULT_REGION
value should be ams3
.
The GHOST_STORAGE_ADAPTER
variables is used by the ghost Docker image to upload static files to your spaces location.
GHOST_STORAGE_ADAPTER_S3_PATH_BUCKET
is supposed to be the name of your spaces. If you look at the image above the name will be the text infront of the region in the url.GHOST_STORAGE_ADAPTER_S3_ASSET_HOST
is the CDN url for your space. In my case that is https://static.devguides.dev/images. As you can see I created a folder called images where I want ghost to upload the images to.GHOST_STORAGE_ADAPTER_S3_ENDPOINT
in my case the endpoint isams3.digitaloceanspaces.com/images
. Again notice that I add the/images
.GHOST_STORAGE_ADAPTER_S3_ACL
should be set topublic-read
. This makes all images you upload available for everyone to read.
When everything is setup all you need to do is to run the command docker-compose up -d
inside the root folder to run the ghost blog. When docker is finished dowloading, the site will be available on the url localhost:2368
After following this guide you should have a functioning Ghost blog with HTTPS and DigitalOcean Spaces as the CDN. If you want to try, a small $5 DigitalOcean droplet should be enough to run the example described above. At the time of writing this blog is running on a $5 droplet.
Do you want to support this blog? Sign up to DigitalOcean using the following referral link: https://m.do.co/c/a51c1128b7df. If you use the link you get $50 credit over 30 days on DigitalOcean.