I'm currently using git to deploy my applications in my different hosts. My codebase being mounted into running Docker images:
docker-compose.yml
services:
app:
image: my.registry.net:5000/my/app
volumes:
- .:/app
# [...]
So my deployments are like that:
$ git pull
$ docker-compose build && docker-compose up -d
$ docker-compose exec app some_dependencies_installation_command
$ docker-compose exec app some_cache_clearing_command
That seems wrong to me for many reasons that you can imagine. Though if something is going wrong I still can revert to my previous git release tag.
I'd like to simplify my deployments by baking my codebase into the image, so I don't use git anymore for deployments but rather rely on image pull. Don't hesitate to tell me if you don't suggest that and why.
I'm tempted to simply add my codebase to the end of my image and mounting just the required stuff in the host:
Dockerfile
# [...]
ADD . /app
docker-compose.prod.yml
services:
app:
image: my.registry.net:5000/my/app
volumes:
- ./config.yml:/app/config.yml
- ./logs:/app/logs
- ./cache:/app/cache
- ./sessions:/app/sessions
# [...]
So once built, I should only have to deploy my images with:
$ docker-compose pull && docker-compose up -d
Would it be the good way to go ? How can I version my image so I can revert it if something goes wrong (since the Dockerfile
actually never changes) ? Also, isn't relying on one layer of the Dockerfile going to pull the entire codebase each time instead of only the diff (like with git) ?
Binding source code onto the container, is usually done to have a quick feedback loop while developing. This is achieved by avoiding rebuilding the image once code changes as done. This technique is mostly useful for local development purposes. For production environments this technique should not be used.
Docker images are designed to be self-contained. All the dependencies that an image needs should be packaged inside the image. Relying on bind mounts to provide the source code or dependencies is not recommended as the resulting Docker image is not portable. Whenever you switch to a new machine, you need to transfer that source code and dependencies to that new machine.
Thus adding the source code into the image is the recommended approach. You should also benefit from the standard Docker workflow, where you build the image giving it a specific tag (usually the version), and push it into a Docker repository. From there on, you only pull the image and start it on any machine that you have.
As for the versioning: When building the image you tag it with the source code version(or git tag or commit id).
docker build -t <image-name>:<version> .
And you also pull a specific version using docker pull <image-name>:<version>
. Using this technique, you can always revert back to any version of the image.