Introduction
As a senior developer who has seen the evolution of development environments over the years, I can't stress enough the importance of containerization. Today, we're going to tackle a common challenge: setting up a consistent Jekyll development environment using Docker Compose. This approach eliminates the classic "it works on my machine" problem and ensures that anyone working on your Jekyll site can get up and running with minimal friction.
Problem Statement
Managing Ruby versions, gem dependencies, and Jekyll installations across different development machines can be a real headache. Whether you're working in a team or maintaining multiple Jekyll sites, ensuring consistency in your development environment is crucial. Docker Compose offers an elegant solution to this problem by containerizing your Jekyll site and its dependencies.
Solution Overview
We'll create a Docker Compose configuration that:
- Uses official Ruby Alpine image for a lightweight container
- Mounts your Jekyll site source code for live development
- Handles Bundler dependencies efficiently
- Enables live reload for development
Implementation
Let's start by creating our Docker Compose configuration. Create a new file called docker-compose.yml in your Jekyll project's root directory:
version: '3'
services:
jekyll:
image: ruby:3.1-alpine
command: >
sh -c "
apk add --no-cache build-base &&
bundle install &&
bundle exec jekyll serve --host 0.0.0.0 --livereload"
environment:
- JEKYLL_ENV=development
ports:
- "4000:4000"
- "35729:35729"
volumes:
- .:/srv/jekyll
- ./vendor/bundle:/usr/local/bundle
working_dir: /srv/jekyll
Configuration Breakdown
Let's examine each component of our Docker Compose configuration:
- Base Image: We're using
ruby:3.1-alpinefor its small footprint while still providing everything we need. - Command: We install build dependencies, run bundle install, and start Jekyll with live reload enabled.
- Ports:
- 4000 - Jekyll's default server port
- 35729 - Live reload functionality
- Volumes:
- Project files mounted to
/srv/jekyll - Bundler dependencies cached in
vendor/bundle
- Project files mounted to
Usage and Best Practices
To start your Jekyll site using Docker Compose, simply run:
docker-compose up
Here are some pro tips for working with your Dockerized Jekyll site:
- Development Workflow: The live reload feature will automatically refresh your browser when you make changes to your source files.
- Dependency Management: When you update your Gemfile, Docker will automatically handle the bundle install on the next startup.
- Cleaning Up: Use
docker-compose downto stop and remove containers when you're done. - Performance Optimization: The cached bundle volume significantly improves startup times on subsequent runs.
For production builds, you might want to create a separate production configuration:
version: '3'
services:
jekyll:
image: ruby:3.1-alpine
command: >
sh -c "
apk add --no-cache build-base &&
bundle install &&
JEKYLL_ENV=production bundle exec jekyll build"
volumes:
- .:/srv/jekyll
- ./vendor/bundle:/usr/local/bundle
working_dir: /srv/jekyll
Troubleshooting Common Issues
Here are some common issues you might encounter and their solutions:
- Permission Issues: If you encounter permission problems with the bundle volume, you may need to adjust the ownership:
chown -R 1000:1000 vendor/bundle - Live Reload Not Working: Ensure your firewall allows connections on port 35729
- Slow Performance: On Windows or macOS, you might experience slower performance due to volume mounting. Consider using Docker's delegated volume mounting option:
volumes: - .:/srv/jekyll:delegated
Conclusion
Dockerizing your Jekyll site might seem like overkill at first, but the benefits become apparent as your project grows or when working in a team. With this setup, you can ensure consistent behavior across different development environments, simplify onboarding for new team members, and maintain a clean separation between your development environment and host system.
Remember, the goal of containerization isn't just to follow the latest trend - it's about creating reproducible environments that make development more efficient and reliable. As you continue to work with this setup, you'll likely find ways to customize it further to match your specific needs.
Next Steps
Consider these advanced topics for further improvement:
- Setting up multi-stage builds for production deployments
- Implementing CI/CD pipelines with your Docker setup
- Optimizing build times with layer caching
- Adding additional services like search functionality