⬆️ ⬇️

A few obscure docker-compose features.

In many instructions from the Internet, they describe a certain minimum of actions, and as a result, a minimum of commands and capabilities.



I decided to make some sort of low-lit features, features. The article does not pretend to be unique, this is me, as a reminder, and perhaps some Padawans will help, starting their journey with docker-compose.



Using multiple docker-compose.yml files



There are complex configurations, where there is a certain base layer of containers, which, say, is always needed. And it usually happens that we take from the neighboring team \ another project \ Internet and finish it to fit our needs. But if there are several commands, then the basic part can be transferred to a common, internal repository. And we get an identical basic part of most projects, which is also versioned.



We describe an example of a basic docker-compose-base.yml.



Suppose this is a customized nginx image with certificates, tuning, and say metrics. And the exporter for prometheus:



version: '2' services: nginx: image: nginx nginx-exporter: image: nginx/nginx-prometheus-exporter 


Now we will describe an example of our docker-compose-app.yml application:



 version: '2' services: backend: image: internal.local/super-app:0.1.2 


To start you need a familiar team with one difference. We will specify 2 docker-compose files:



 docker-compose up -d -f docker-compose-base.yml -f docker-compose-app.yml 


And voila, we get a set of services, as if they were described in a single docker-compose file!



There is also a second use case for multiple files, through the use of the extends directive.



docker-compose-base.yml:



 version: '2' services: nginx: image: nginx nginx-exporter: image: nginx/nginx-prometheus-exporter 


docker-compose-app.yml:



 version: '2' services: backend: image: internal.local/super-app:0.1.2 ###      web: extends: #     (   ) file: docker-compose-base.yml #       service: nginx web-exporter: extends: file: docker-compose-base.yml service: nginx-exporter 


Addition from iSlava :

You can describe all compose files in environment variables, and use docker-compose up -d without specifying the files manually:



 COMPOSE_PATH_SEPARATOR=: COMPOSE_FILE=docker-compose-base.yml:docker-compose-app.yml 


Which option to choose - you choose. All individually, I just wanted to show the options =)



Docker-compose inheritance



The following example requires docker-compose > = 2.4

It is also a rather interesting feature, and it is actually mentioned in few places.

This functionality allows us to describe several services of the same type in the docker-compose file, while not duplicating their description, namely inheriting.

For example, we have this file:



 version: '2.4' services: backend: image: internal.local/super-app:0.1.2 ports: - 8080:8080 - 9090:9090 volumes: - ./conf/some.conf:/etc/app/some.conf:ro 


And there was a need to raise several containers, but with some differences, we can of course "accumulate" and change, and we can do this:



 version: '2.4' services: backend: &base-app #          image: internal.local/super-app:0.1.2 ports: - 8080:8080 - 9090:9090 volumes: - ./conf/some.conf:/etc/app/some.conf:ro backend-2: <<: *base-app # ports: #    - 8081:8080 


Thus, we get the opportunity to change in one place than to rule in the description of each container.

There is another option to bring to the root area, for example:



 version: '2.4' services: x-backend: #   "x-"  ,    . &base-app image: internal.local/super-app:0.1.2 ports: - 8080:8080 - 9090:9090 volumes: - ./conf/some.conf:/etc/app/some.conf:ro backend: <<: *base-app # backend-2: <<: *base-app # ports: #    - 8081:8080 


Resource Limits



Starting from version 2.2, you can use resource limits for containers, in fact, from version 2.1, but not everything has been delivered there =)

There is a nuance! In version 3, these features are removed! There is an emphasis on docker swarm.



The simplest example of limiting resources by CPU, MEM:



 version: '2.2' services: backend: cpus: 1.5 #   . cpuset: '0,3' #     . mem_limit: 1gb #  1  memswap_limit: 2gb # SWAP   . oom_kill_disable: true #   ,    OOM Killer        ,       . image: internal.local/super-app:0.1.2 ports: - 8080:8080 - 9090:9090 volumes: - ./conf/some.conf:/etc/app/some.conf:ro 


Packing images to archive



Unfortunately, it is not always possible to push the images in your docker registry or your cloud. Sometimes it's worth having to collect images from a docker-compose file and send, say, a file archive. I sometimes do this for a long time with my hands, so I sketched a simple script, all of a sudden someone will come in handy:



 #!/bin/bash dc=${1} if [ ! -z ${dc} ] && [ -f ${dc} ]; then echo "Saving docker images from file ${dc}..." images=`grep image: ${dc} | awk '{print $2}'` docker save ${images} | gzip > docker-images.gz echo "Success!" else echo "ERROR! You must set path to docker-compose.yml as argument!" fi 


We save in the file we will tell docker-compose-images-save.sh

We give the right to perform:

chmod +x docker-compose-images-save.sh

Run, and pass the path to the docker-compose file as an argument:

./docker-compose-images-save.sh /home/some_user/docker-compose-app.yml

At the output we get in the folder from where the script called the archive with images - docker-images.gz

In any available way we send to a remote server.

Now on the remote server is enough to perform:

gzip -cd docker-images.gz | docker load

All images will be loaded into the local registry, after which you can safely run here.

docker-compose up -d , since all the images are already in the local registry on the Internet, the docker will not work.



IPv6 forwarding



In certain tasks, ipv6 is extremely useful, take at least a caveat that Roskomnadzor passes all traffic through ipv6 without problems, and the same telegram bot works without problems.

I will consider the situation when ipv6 is not on your machine, be it a virtual machine, or a server on the Internet.

You need to make sure that ipv6 is enabled at the system level:



  sysctl net.ipv6.conf.all.disable_ipv6 


The value should be 0, if not, change:



  sysctl -w net.ipv6.conf.all.disable_ipv6=0 


Install miredo (This is a service with a built-in VPN to the server, which will give us a public ipv6)



  apt-get install miredo -y 


Check that the service is running:



  systemctl status miredo 


Check that we got the ipv6 address:



  ifconfig teredo 


Register in /etc/docker/daemon.json



  { "ipv6": true, "fixed-cidr-v6": "2001:db8:1::/64" } 


Restart docker:



  systemctl restart docker 


Well, it remains to enable NAT for ipv6 so that the internal addresses of our container can go to the outside world through our teredo interface:



  ip6tables -t nat -A POSTROUTING -o teredo -j MASQUERADE 


We raise the docker container we need, and it can be published via the ipv6 address.



The given example with sysctl and iptables will work before the reboot, if you need to do it on an ongoing basis, you should see the instructions for your distribution, there are differences.

I hope someone the information provided here will be useful.



')

Source: https://habr.com/ru/post/459618/



All Articles