Md Toy Blog

Workflows

Mon Jul 20 2020 00:00:00 GMT+0000 (Coordinated Universal Time)

These are a set of workflows for a very early stage development-production environment using docker containers.

It heavily relies on gbili/git-server-hooks which is a simple git server with a post-receive hook (or any other hook you would like to add to it for that matter) in charge of deploying the new code to some directory readable by the production application container.

This production application container can for example be based on node-app-js or node-app-ts etc.

Production application container

In order to present the application to the user, these containers need to somehow get the main application code from the developer's machine.

A few ways can be used:

  1. get the code from the development machine prepacking it with a Dockerfile build
  2. git push the code to the production host, and somehow let the running container use the newly pushed code

Option 1: Packaging the code with docker build

The more standard way, seems to be the option 1. It requires:

Independently:

  • git add
  • git commit
  • git push

Once version controlled, we need to:

  • In dev machine docker build (probably only rebuilding the last layers)
  • In dev machine docker push
  • In host machine docker-compose restart

There are ways to link both parts, with client git-hooks post-commit for example.

Why not use this way then ? Big question left unanswered. Especially if there is no limitation in creating a script to do the whole thing in a single command.

Option 2: Git Pushing to a running container

In this approach we rely on git-server-hooks container. It's a simple Git server for a single user.

And another to fix permissions on the shared volume. In order to deploy the pushed git code to the running app container, we need to make sure that we give the proper permissions to the running app container. And it should be easy except it seems git determines what rights should be attributed to the checkedout code, and they are very few.

Node: So we use a different strategy, which makes sure every X seconds that the app directory that git just checked out to, has the proper permissions for node to run the app.

Then again, even after fixing the permissions to make the new deployed code accessible to the app, we still need to have a way to npm i and restart the app.

Node: Since we need to restart anyway, this additional container, does not even need to exist if the permissions are fixed at docker-compose restart by the real app's start.sh script.

Note: that there is a nuance on whether we are serving a static contents or not. If the content is static, there would be no need to restart the container because the new static content would frictionlessly be made available.

All in all it requires these steps:

  • git add
  • git commit
  • git push

Once version controlled:

  • In host machine docker-compose restart

With this setup we are able to skip the docker image build/push/pull cycle. Of course if the image was big, it could be an advantage. But for most it does seem more of a trouble than an advancement.

We used option 2

One would wonder why stick with option 2 when we have determined that the first is the standard, plus the second requires gymnastics using root on an entry point script ect. Which are known bad practices.

But we do bad decisions… So here is the workflow anyway.

  1. Make sure to have a git-server-hooks container running and accessible at some url. And with your ssh keys
  2. Create a repository for the application on the server's git-server-hooks:
  • for that use git-server-hooks-repo-add's docker-compose.yml adjusted to the new repo
  • docker-compose up that to create the temporary container that will create the repo
  1. In the development machine, configure the git repo to push to the new host remote
  2. git commit -am "feat: new amazing thing" and git push live master
  3. This will push the code and deploy it to the git-server-hooks_node-server volume
  4. Get an image of node-app-js in the host machine, and configure it to serve the app using:
  • nginx-proxy network for the domain to be ssled
  • git-server-hooks_node-server's volume as the app's root directory where the git deployed code and package.json are and where npm i can be run
  1. docker-compose up or docker-compose restart after git pushing to the live remote.
  • Use the dotfiles/git-pushup -d <docker-compose.yml's_dir> in order to push the code to git and the production volume and immediately restart the container.
    • This will use docker-restart-service script on the host to restart the proper service living in the -d dir

These are the initial steps, but once you have everything setup, every commit requires you to do a simple git-pushup -d myapp_dir in order to update the app's container.

How would it look like using option 1

We could combine the already existing dotfiles's script docker-build-push -t <remote/tag:num> to get it triggered after a git push and add a flush-start to remove the old image and rebuild. But deleting the images from the registry and then pulling will take some time. Then, we would have the advantage of being able to add some ci in the Dockerfile. We would no longer need to use an entry point which is a shell script (even though we run it using exec to make it first PID).