Welcome to the GraphQL Docker Lab! This comprehensive lab will guide you through setting up a GraphQL server inside a Docker container, understanding GraphQL query and mutation syntax, and completing hands-on exercises to interact with the API using Postman.
Before starting the lab, ensure you have the following installed on your system:
- Purpose: To clone the repository and version control
- Download: Git for Windows | Git for Mac | Git for Linux
- Verification: Open terminal/command prompt and run
git --version
- Purpose: To build and run the GraphQL server in a containerized environment
- Download: Docker Desktop
- Verification: Run
docker --versionanddocker-compose --version - Note: Ensure Docker Desktop is running before proceeding
- Purpose: To test GraphQL API endpoints and send HTTP requests
- Download: Postman
- Alternative: You can also use curl, Insomnia, or any REST client
- Purpose: If you want to run the server locally without Docker
- Download: Node.js
- Verification: Run
node --versionandnpm --version
- Purpose: For code editing and better development experience
- Download: VS Code
- Operating System: Windows 10/11, macOS 10.14+, or Linux
- RAM: Minimum 4GB (8GB recommended)
- Storage: At least 2GB free space
- Internet Connection: Required for initial setup and data seeding
GraphQL is a query language for APIs that provides a single endpoint for all data operations. Unlike REST APIs, GraphQL allows clients to request exactly the data they need.
GraphQL uses a type system to define the structure of your data:
type Book {
id: ID!
title: String!
author: String!
publishedYear: Int
}
type Query {
books: [Book!]!
book(id: ID!): Book
}
type Mutation {
addBook(title: String!, author: String!, publishedYear: Int): Book
updateBook(id: ID!, title: String, author: String, publishedYear: Int): Book
deleteBook(id: ID!): String
}query {
books {
id
title
author
publishedYear
}
}query {
book(id: "BOOK_ID") {
id
title
author
publishedYear
}
}query GetBook($bookId: ID!) {
book(id: $bookId) {
id
title
author
publishedYear
}
}mutation {
addBook(title: "The Great Gatsby", author: "F. Scott Fitzgerald", publishedYear: 1925) {
id
title
author
publishedYear
}
}mutation {
updateBook(id: "BOOK_ID", title: "Updated Title", author: "Updated Author") {
id
title
author
publishedYear
}
}mutation {
deleteBook(id: "BOOK_ID")
}mutation AddBook($title: String!, $author: String!, $year: Int) {
addBook(title: $title, author: $author, publishedYear: $year) {
id
title
author
publishedYear
}
}| Operation | REST | GraphQL |
|---|---|---|
| GET | GET /books |
query { books } |
| GET by ID | GET /books/123 |
query { book(id: "123") } |
| POST | POST /books |
mutation { addBook(...) } |
| PUT | PUT /books/123 |
mutation { updateBook(id: "123", ...) } |
| DELETE | DELETE /books/123 |
mutation { deleteBook(id: "123") } |
Follow these steps to set up your GraphQL development environment:
git clone https://github.com/Munir-2001/Graph-QL-Design-Architecture.git
cd Graph-QL-Design-Architecturedocker --version
docker-compose --versiondocker build -t graphql-docker-lab .Expected Output:
[+] Building 15.2s (8/8) FINISHED
=> [internal] load build definition from Dockerfile
=> => transferring dockerfile: 32B
=> [internal] load .dockerignore
=> => transferring .dockerignore: 2B
=> [internal] load metadata for docker.io/library/node:18-alpine
=> [1/4] FROM docker.io/library/node:18-alpine
=> [internal] load build context
=> => transferring context: 2.00kB
=> [2/4] WORKDIR /app
=> [3/4] COPY package*.json ./
=> [4/4] RUN npm install
=> exporting to image
=> => exporting layers
=> => exporting manifest sha256:...
=> => writing image sha256:...
=> => naming to docker.io/library/graphql-docker-lab:latest
docker run -p 4000:4000 graphql-docker-labExpected Output:
Fetching initial data from Open Library...
Seeded 25 books.
Your Server ready at http://localhost:4000/
Open your browser and navigate to: http://localhost:4000/
You should see the Apollo Server landing page with GraphQL Playground.
If you prefer to run locally:
npm install
npm start-
Port 4000 already in use
# Find process using port 4000 netstat -ano | findstr :4000 # Windows lsof -i :4000 # Mac/Linux # Use different port docker run -p 4001:4000 graphql-docker-lab
-
Docker not running
- Start Docker Desktop
- Wait for it to fully initialize
-
Permission issues (Linux/Mac)
sudo docker build -t graphql-docker-lab . sudo docker run -p 4000:4000 graphql-docker-lab
Complete these 8 activities to master GraphQL operations. Each activity builds upon the previous ones.
-
Open Postman
-
Set up a new request:
- Method:
POST - URL:
http://localhost:4000/ - Headers:
Content-Type: application/json - Body: Select
rawandJSON
- Method:
-
Request Format:
{ "query": "YOUR_GRAPHQL_QUERY_HERE" }
Objective: Retrieve all books from the GraphQL server
GraphQL Query:
query {
books {
id
title
author
publishedYear
}
}Postman JSON Body:
{
"query": "query { books { id title author publishedYear } }"
}Expected Result: An array of 25 books (initially seeded from Open Library)
Learning Points:
- Basic query syntax
- Field selection
- Array responses
Objective: Retrieve a specific book using its unique identifier
Prerequisites: Complete Activity 1 to get a valid book ID
GraphQL Query:
query {
book(id: "BOOK_ID") {
id
title
author
publishedYear
}
}Postman JSON Body (replace BOOK_ID with actual ID):
{
"query": "query { book(id: \"_addidhere_\") { id title author publishedYear } }"
}Expected Result: A single book object or null if ID doesn't exist
Learning Points:
- Query with arguments
- Single object responses
- Error handling for invalid IDs
Objective: Create a new book in the system
GraphQL Mutation:
mutation {
addBook(title: "The Art of Programming", author: "John Developer", publishedYear: 2024) {
id
title
author
publishedYear
}
}Postman JSON Body:
{
"query": "mutation { addBook(title: \"The Art of Programming\", author: \"John Developer\", publishedYear: 2024) { id title author publishedYear } }"
}Expected Result: The newly created book with generated ID
Learning Points:
- Mutation syntax
- Creating new resources
- Return value specification
Objective: Modify an existing book's information
Prerequisites: Complete Activity 3 or use an existing book ID
GraphQL Mutation:
mutation {
updateBook(id: "BOOK_ID", title: "Updated Programming Guide", author: "Jane Expert") {
id
title
author
publishedYear
}
}Postman JSON Body (replace BOOK_ID):
{
"query": "mutation { updateBook(id: \"abc123def\", title: \"Updated Programming Guide\", author: \"Jane Expert\") { id title author publishedYear } }"
}Expected Result: The updated book object
Learning Points:
- Partial updates
- Mutation with multiple parameters
- Updating existing resources
Objective: Remove a book from the system
Prerequisites: Use a valid book ID from previous activities
GraphQL Mutation:
mutation {
deleteBook(id: "BOOK_ID")
}Postman JSON Body (replace BOOK_ID):
{
"query": "mutation { deleteBook(id: \"abc123def\") }"
}Expected Result: Success message: "Book with id abc123def deleted."
Learning Points:
- Delete operations
- String return types
- Resource removal
Objective: Find books published in a particular year (e.g., 1935)
Note: Since the current server doesn't support filtering via GraphQL arguments, we'll fetch all books and filter client-side.
GraphQL Query:
query {
books {
id
title
author
publishedYear
}
}Postman JSON Body:
{
"query": "query { books { id title author publishedYear } }"
}Manual Filtering Steps:
- Execute the query
- Look through the response for books where
publishedYearequals your target year - Count how many books were published in that year
Expected Result: List of books published in the specified year
Learning Points:
- Client-side filtering
- Understanding server limitations
- Data analysis
Objective: Find all books written by a specific author
GraphQL Query:
query {
books {
id
title
author
publishedYear
}
}Postman JSON Body:
{
"query": "query { books { id title author publishedYear } }"
}Manual Filtering Steps:
- Execute the query
- Filter results for books where
authorfield matches your target author - List all books by that author
Expected Result: Array of books by the specified author
Learning Points:
- Client-side data filtering
- Author-based queries
- Data organization
Objective: Test error handling by attempting to update a non-existent book
GraphQL Mutation:
mutation {
updateBook(id: "INVALID_ID", title: "This Book Doesn't Exist") {
id
title
author
publishedYear
}
}Postman JSON Body:
{
"query": "mutation { updateBook(id: \"INVALID_ID\", title: \"This Book Doesn't Exist\") { id title author publishedYear } }"
}Expected Result:
{
"data": {
"updateBook": null
}
}Learning Points:
- Error handling in GraphQL
- Null responses
- Graceful failure handling
- Activity 1: Successfully fetched all books
- Activity 2: Retrieved a book by ID
- Activity 3: Created a new book
- Activity 4: Updated an existing book
- Activity 5: Deleted a book
- Activity 6: Filtered books by publication year
- Activity 7: Found books by specific author
- Activity 8: Handled invalid operations
Try to add multiple books in a single mutation (hint: you may need to modify the schema)
Modify the server to support filtering by year and author in the GraphQL schema
Implement proper error handling for edge cases
- Always set
Content-Type: application/jsonheader in Postman - Book IDs are randomly generated - save them from queries before using in mutations
- Data is stored in-memory; restarting the container resets to initial state
- GraphQL is case-sensitive
- Use double quotes for string values in JSON
- Always specify the fields you need in your queries (avoid over-fetching)
- Use meaningful variable names in your mutations
- Test error scenarios to understand system behavior
- Document your queries for future reference
- GraphQL Playground - Interactive GraphQL IDE
- GraphiQL - Browser-based GraphQL IDE
- Apollo Studio - GraphQL development platform
- Ensure Docker container is running
- Check if port 4000 is available
- Verify the URL is correct:
http://localhost:4000/
- Check for proper quotes (use double quotes in JSON)
- Ensure proper nesting of objects
- Validate GraphQL syntax
- Verify the server is seeded with initial data
- Check if the query syntax is correct
- Ensure you're using the right field names
- Check Docker Desktop is running
- Ensure all files are in the correct directory
- Try building with
--no-cacheflag:docker build --no-cache -t graphql-docker-lab .
Congratulations on completing the GraphQL Docker Lab! 🎉
You should now have a solid understanding of:
- GraphQL syntax and operations
- Docker containerization
- API testing with Postman
- CRUD operations in GraphQL
- Error handling and edge cases