My current web services are running on the same virtual machine. They include the WordPress (a.k.a the blog), Nextcloud, and Redmine, etc. One way to keep them secure is to keep them updated. It can be a headache when I need to find new dependencies for the newer versions. It becomes more convinient when I dockerize the web services.
The drawback of putting on the virtual machine is
- The packages coming with the OS on the virtual machine aren't always updated. Often time I have to run a custom script to install them.
- Installing via custom scripts may leave the system on an unsustainable state. I forget what's done and how to undo it.
- It's possible that different web services require different versions.
I think I'm done with those struggles every time I update the services. So I decide to put them into docker.
With docker, I can
- Easily know what I install on the docker image.
- Re-create the image and don't worry about undoing the custom scripts.
- Isolate different services if they have conflicts on the packages.
- Choose the base OS image if it is needed.
I spend some time writing the Dockerfile.
- Figure out the dependencies. Luckily, with the right OS image, I can just use its package manager to install instead of running custom scripts. This part is straightforward since I can read the documents.
- Use VOLUME and save the configuration on the host instead of inside the container. This can also save me a lot of efforts when I iterate the image building.
There are two technical challenges I have to tackle and spent most time.
- Certbot needs to use systemd to control apache when I add SSL. After a few search, I find docker systemctl replacement. It creates a script to replace the command. The author provides some Dockerfile examples for different images. I modify that to use a custom script running a bunch of other stuffs and
systemctl start httpdfollowed by
bash. The script needs to start a command that's long running. The container will stop after the command ends.
- Use cron inside the container. I find a good discussion on Stack Overflow. The main steps in Dockerfile are
# Copy hello-cron file to the cron.d directory
COPY hello-cron /etc/cron.d/hello-cron
# Give execution rights on the cron job
RUN chmod 0644 /etc/cron.d/hello-cron
# Apply cron job
RUN crontab /etc/cron.d/hello-cron
There are however something I can do only when the system runs. That's done in the custom script I set to run in CMD. I use flags to make sure it only runs once for that container.
With the change, I remove the unnecessary packages and settings from my virtual machine. I can control how the environment is setup for different web services.