What's the difference between a stack file and a Compose file? - docker

I'm learning about using Docker Compose to deploy applications in multiple containers, across multiple hosts. And I have come across two configuration files - stack file, and Compose file.
From the Cloud stack file YAML reference, it states a stack file is a file in YAML format that defines one or more services, similar to a docker-compose.yml file but with a few extensions.
And from this post, it states that stacks are very similar to docker-compose except they define services while docker-compose defines containers.
They look very similar, so I am wondering when I would use the stack file, and when to use the Compose file?

Conceptually, both files serve the same purpose - deployment and configuration of your containers on docker engines.
Docker-compose tool was created first and its purpose is "for defining and running multi-container Docker applications" on a single docker engine. (see docker compose overview )
You use docker-compose up to create/update your containers, networks, volumes and so on.
Where Docker Stack is used in Docker Swarm (Docker's orchestration and scheduling tool) and, therefore, it has additional configuration parameters (i.e. replicas, deploy, roles) that are not needed on a single docker engine.
The stack file is interpreted by docker stack command. This command can be invoked from a docker swarm manager only.
You can convert docker-compose.yml to docker-cloud.yml and back. However, as stated in your question, you must pay attention to the differences. Also, you need to keep in mind that there're different versions for docker-compose. Presently, the latest version is version 3. (https://docs.docker.com/compose/compose-file/)
Edit: An interesting blog, that might help to understand the differences, can be found here https://blog.nimbleci.com/2016/09/14/docker-stacks-and-why-we-need-them/

Note: The question guesses that the Docker Cloud reference is the go-to for understanding stack, and it is useful, but that isn't the authoritative source on stack vs compose -- instead that is a guide that is specific to Docker's hosted service: "Docker Cloud provides a hosted registry service with build and testing facilities." For file documentation, see the Compose file version 3 format -- although it is named "Compose", this is the authoritative place for which features work with both compose and swarm/stack, and how.
You can specify a group of Docker containers to configure and deploy in two ways:
Docker compose (docker-compose up)
Docker swarm (docker swarm init; docker stack deploy --compose-file docker-stack.yml mystack)
Both take a YAML file written in the Docker Compose file version 3 format. That reference is the primary source documenting both docker-compose and docker swarm/stack configuration.
However, there are specific differences between what you can do in the two yml files -- specific options, and specific naming conventions:
Options
The available service configuration options are documented on the Compose file reference page -- usually with a note at the bottom of an option entry describing it as ignored either by docker stack deploy or by docker-compose up.
For example, the following options are ignored when deploying a stack in swarm mode with a (version 3) Compose file:
build, cap_add, cap_drop, cgroup_parent, container_name, depends_on, devices, external_links, links, network_mode, restart, security_opt, stop_signal, sysctls, tmpfs (version 3-3.5), userns_mode
...while some options are ignored by docker-compose, yet work with docker stack deploy, such as:
deploy, restart_policy
When run from the command line, docker stack deploy will print warnings about which options it is ignoring:
Ignoring unsupported options: links
File naming
For docker-compose up the default file name is docker-compose.yml if no alternate file name is specified using -f (see the compose reference). It is common to use this default name and run the command without an argument.
For docker stack deploy there is no default file given in the docker stack deploy reference. You can use whatever name you want, however here are three conventions:
use docker-stack.yml, as used in the official Docker for Beginners Ch.3: Deploying an app to a Swarm.
use docker-cloud.yml, as used in the Docker Cloud Stack YML reference for the Docker Cloud service.
use docker-compose.yml -- the old default name for the Compose file format.

Related

Volume or directory shared between services and runner container in Gitlab CI

I'm specifically trying to get files from services (docker containers) in a Gitlab CI job to the runner container. *I could provide more details on exactly what I'm trying to do, but I'd like to keep this question fairly generic and platform/language agnostic.
Essentially I have the following .gitlab-ci.yml:
image: customselfhostedimage-redacted
services:
- postgres:latest
- selenium/standalone-chrome
...
There are files being downloaded in one of the service containers (selenium) which I need to gain access to from the main container being run by the Gitlab runner. Unfortunately I can not seem to find any method to create a volume mount or share of some sort between service containers and the host (※ NOTE: This was not true, see accepted answer.). Adding commands to specifically copy files from within service containers is also not an option for me. I'm aware of multiple issues requesting such functionality, such as this one:
https://gitlab.com/gitlab-org/gitlab-runner/-/issues/3207
The existence of these open issues indicates to me there is not currently a solution.
I have tried to specify volumes in config.toml as has been in comments in various Gitlab CI issues related to this subject, but this does not seem to create volume mounts on service containers?
Is there any way to create volume mounts inside service containers accessible to the runner/runner container, or if not is there any simple solution to make files accessible from (and possibly between) service containers?
※ NOTE: This is NOT a docker-compose question, and it is NOT a docker-in-docker question.
If you self-host your runners, you can add volumes to the runner configuration, which applies to services and job containers alike.
Per the documentation:
GitLab Runner 11.11 and later mount the host directory for the defined services as well.
For example:
[runners.docker]
# ...
volumes = ["/path/to/bind/from/host:/path/to/bind/in/container:rw"]
This path will be available both in the job as well as in containers defined in services:. But keep in mind that the data (and changes) are available and persisted across all jobs that use this runner.

Moving my Docker application which is a collection of containers

I have been reading various articles for migrating my Docker Application into a different machine. All the articles talk about “docker commit” or “export/ import”. This only refers to a single Container, which is first converted to an Image and then we do a “docker run” on the new machine.
But my application is usually made up of several containers, because I am following the best practice of segregating different services.
The question is, how do I migrate or move all the containers that have been configured to join together and run as one. I don’t know whether “swarm” is the correct term for this.
The alternative I see is - simply copy the “docker-compose” and “dockerfile” into the new machine and do a fresh setup of the architecture. Then I copy all the application files. It runs fine.
My purpose, of course is not the only solution, but it's quite nice:
Create docker images in one machine (where you need your Dockerfile)
Upload images to a docker registry (you can use your own docker hub account, or maybe a nexus, or whatever)
2.1. It's also recommended to tag with version your images, and protect overwritting an image with the same version and different code.
Use docker-compose (it's recommended define a docker network for all docker that have to interact among them) to deploy (docker-compose up is like several docker run, but easier to mantain.)
You can deploy in several machines just using the same docker-compose.yml to deploy and access to your registry.
4.1. Deploy can be done in a single host, swarm, kubernetes... (you'd have to translate your docker-compose.yml to kubectl yml file for that)
I agree to the docker-compose suggestion. And to store your images in a registry or on your local machine. Each section in your docker compose file will be separated per service. Each service will have to be written in YAML format.
You are going to want version 3 YAML I believe. Then from there you code something like below. But each service will use your Dockerfile image in your registry or locally in your folder.
version : '3'
services:
drupal:
image:
......ports, volumes, etc
postgres:
image:
......ports, volumes, etc
Disclosure: I took a Docker Course from Bret Fisher on Udemy.

Does the Docker message: "Ignoring unsupported options: restart" mean the restart policy is ignored?

Using docker stack deploy, I can see the following message:
Ignoring unsupported options: restart
Does it mean that restart policies are not in place?
Do they have to be specified outside the compose file?
You can see this message for example with the
Joomla compose file available at the bottom of that page.
To start the compose file:
sudo docker swarm init
sudo docker stack deploy -c stackjoomla.yml joomla
A Compose YAML file is used by both docker-compose tool, for local (single-host) dev and test scenarios, and Swarm Stacks, for production multi-host concerns.
There are many settings in the Compose file which only work in one tool or the other (docker-compose up vs. docker stack deploy) because some settings are specific to dev and others specific to production clusters. It's OK that they are there, and you'll see warnings in either tool when there are settings included that the specific tool will ignore. This is commonly seen for build: settings (which are docker-compose only) and deploy: settings (which are Swarm Stacks only).
The whole goal here is a single file you can use in both tools, and the relevant sections of the compose file are used in that scenario, while the rest are ignored.
All of this can be referenced for the individual setting in the compose file documentation. If you're often working in Compose YAML, I recommend always having a tab open on this page, as I've referenced it almost daily for years, as the spec keeps changing (we're on 3.4+ now).
docker-compose does not restart containers by default, but it can if you set the single-setting restart: as documented here. But that setting doesn't work for Swarm Stacks. It will show up as a warning in a docker stack deploy to remind you that the setting will not take effect in a Swarm Stack.
Swarm Stacks use the restart_policy: under the deploy: setting, which gives finer control with multiple sub-settings. Like all Stack's, the defaults don't have to be specified in the compose file, and you'll see their default settings documented on that docs page.
There is a list on that page of the settings that won't work in a Swarm Stack, but it looks incomplete as the restart: setting should be there too. I'll submit a PR to fix that.
Also, in the Joomla example you pointed us too, that README seems out of date as well, as it includes links: in the compose example, which are depreciated as of Compose version 2, and not needed anymore (because all containers on a custom virtual network can reach each other now).
If you docker-compose up your application on a Docker host in standalone mode, all that Compose will do is start containers. It will not monitor the state of these containers once they are created.
So it is up to you to ensure that your application will still work if a container dies. You can do this by setting a restart-policy.
If you deploy an application into a Docker swarm with docker stack deploy, things are different.
A stack is created that consists of service specifications.
Docker swarm then makes sure that for each service in the stack, at all times the specified number of instances is running. If a container fails, swarm will always spawn a new instance in order to match the service specification again. In this context, a restart-policy does not make any sense and the corresponding setting in the compose file is ignored.
If you want to stop the containers of your application in swarm mode, you either have to undeploy the whole stack with docker stack rm <stack-name> or scale the service to zero with docker service scale <service-name>=0.

Any reasons to not use Docker Swarm (instead of Docker-Compose) on a single node?

There's Docker Swarm (now built into Docker) and Docker-Compose. People seem to use Docker-Compose when running containers on a single node only. However, Docker-Compose doesn't support any of the deploy config values, see https://docs.docker.com/compose/compose-file/#deploy, which include mem_limit and cpus, which seems like nice/important to be able to set.
So therefore maybe I should use Docker Swarm? although I'm deploying on a single node only. Also, then the installation instructions will be simpler for other people to follow (they won't need to install Docker-Compose).
But maybe there are reasons why I should not use Swarm on a single node?
I'm posting an answer below, but I'm not sure if it's correct.
Edit: Please note that this is not an opinion based question. If you have a look at the answer below, you'll see that there are "have-to" and "cannot-do" facts about this.
For development, use Docker-Compose. Because only Docker-Compose is able to read your Dockerfiles and build images for you. Docker Stack instead needs pre-built images. Also, with Docker-Compose, you can easily start and stop single containers, with docker-compose kill ... and ... start .... This is useful, during development (in my experience). For example, to see how the app server reacts if you kill the database. Then you don't want Swarm to auto-restart the database directly.
In production, use Docker Swarm (unless: see below), so you can configure mem limits. Docker-Compose has less functionality that Docker Swarm (no mem or cpu limits for example) and doesn't have anything that Swarm does not have (right?). So no reason to use Compose in production. (Except maybe if you know how Compose works already and don't want to spend time reading about the new Swarm commands.)
Docker Swarm doesn't, however, support .env files like Docker-Compose does. So you cannot have e.g. IMAGE_VERSION=1.2.3 in an .env file and then in the docker-compose.yml file have: image: name:${IMAGE_VERSION}. See https://github.com/moby/moby/issues/29133 — instead you'll need to set env vars "manually": IMAGE_VERSION=SOMETHING docker stack up ... (this actually made me stick with Docker-Compose. + that I didn't reasonably quickly find out how to view a container's log, via Swarm; Swarm seemed more complicated.)
In addition to #KajMagnus answer I should note that Docker Swarm still don't support Linux Capabilities as Docker [Compose] do. You can learn about this issue and dive into Docker community discussions here.

docker create service vs. docker deploy stack

The new Docker 1.13.0 release introduced docker stack deploy.
docker stack deploy adds support of deploying services from a docker-compose.yml file directly.
Are the command docker service create and docker deploy stack creating the same service, just i two different ways?
Are there any special features added the service by creating it with docker deploy stack?
Im a bit confused, and can't find any information about this subject.
Thanks in advance
A stack is a collection of services. This is similar to how a compose file defines a group of containers to run. So if you only need to run a single service, you can do so with a docker service create. If you need to deploy a collection of services, or use a definition from a compose file as your definition for the service(s), then you would deploy them with docker stack deploy.

Resources