Building a Scalable Bucket List API with Go-Chi, PostgreSQL, and Docker
Are you tired of using full-blown web frameworks for your HTTP services? Look no further! Go-Chi is a lightweight router library that provides modular request handling without the extra baggage. In this tutorial, we’ll show you how to build a containerized bucket list API using Go-Chi, PostgreSQL, and Docker.
What You’ll Learn
By the end of this tutorial, you’ll have a fully functional API that exposes the following endpoints:
- POST /items to add a new item to the list
- GET /items to fetch all existing items in the list
- GET /items/{itemId} to fetch a single item from the list using its ID
- PUT /items/{itemId} to update an existing item
- DELETE /items/{itemId} to delete an item from the list
Prerequisites
Before we dive in, make sure you have the following:
- Go (version 1.14 or higher)
- PostgreSQL installed
- Docker and docker-compose installed to manage our services
- Basic knowledge of Go and PostgreSQL
Getting Started
Create a new project folder and initialize the Go module. Then, install the necessary dependencies, including go-chi/chi, go-chi/render, and lib/pq.
Project Structure
Create the following folders and files to match the layout below:
- db: Interacts directly with our database
- handler: Creates and handles our API routes using Chi
- models: Contains Go structs that can be bound to database objects or transformed into their equivalent JSON format
- Dockerfile: Defines the base image and commands required to have our API server up and running
- docker-compose.yml: Defines our app dependencies (the server using the Dockerfile and the database using the official Postgres Docker image)
*.env: Holds our application environment variables (such as database credentials) - main.go: Our application entry point, responsible for reading environment variables, setting up the database, and starting and stopping the API server
Decomposing Services with Docker-Compose
Let’s set up the Dockerfile to build the API server into a single binary file, expose the server port, and execute the binary on startup. Then, open the docker-compose.yml file and declare the server and database services.
Setting Up the Database
We’ll use Golang-Migrate to manage our database migrations. Install the migrate binary and generate the database migrations by running the command below. This will create two SQL files in the db/migrations folder.
Using Structs as Models
We need models to interact with the database from our Go code. Create a new file in the models folder and add the code to define the Item struct. With Chi, we can render this struct as a JSON object to our API consumer.
Interacting with PostgreSQL
Edit the db.go file to manage the connection to our PostgreSQL database. Then, edit the item.go file to make it responsible for interacting with the items table.
Wiring Up Our Route Handlers
We’re now ready to leverage Chi’s powerful routing features. Initialize the route handlers in handler/handler.go and implement the code to handle HTTP errors such as 404 Not Found and 405 Method Not Allowed.
Bringing It All Together
Having set up the individual components of our API, let’s tie them together in the main.go file. Open the file and add the code to create a new database connection, start the API server, and handle shutdown.
Testing Our API with cURL
We’re now ready to test our application using docker-compose. Run the command below to build and start up the services. Then, test out the individual endpoints using Postman or by running the following curl commands.
That’s it! You’ve successfully built a scalable bucket list API using Go-Chi, PostgreSQL, and Docker. The complete source code is available on Gitlab. Feel free to create an issue or reach out to us with questions or feedback.