.circleci/config.yml with more than one Docker image


#1

Hello,

Following the example at https://circleci.com/docs/2.0/language-android/
I added a .circleci/config.yml to my git repo and everything seems to be fine. Circleci builds perform as expected for my android app

However Id like to add some static data (eg precompiled c++ libraries such as boost, which should change orthogonally to the android version in the current docker: image ( ie circleci/android:api-27-alpha).

I could presumably create a new image based on circleci/android:api-27-alpha, add the static data (libraries) to it, push to docker hub, and use this as the docker image in my .circle/config.yml

However, this doesnt seem as elegant as having 2 images - one with the android sdk, and one with the static data, and each is independent of the other.

If I were just using docker (compose) I would create a docker-compose.yml with the contents below.
The ‘data’ image and ‘droid’ image can change independently, and yet the droid image can access the data in the other through shared volumes,

Is there any nice way to modify the example at https://circleci.com/docs/2.0/language-android/ so that it does something like this? And if so does it require a paid circleci account?

Many Thanks in Advance

version: '3'
services:
    droid: 
        image: circleci/android:api-27-alpha
        container_name: ctr_droid
        command: tail -F anything   # dummy command keep container busy, so it wont exit immediately 
        volumes:
            - data-vol:/some_dir    # make volume named "data-vol" accessible to this ctrs /tmp/somedir    .. since it doesnt exist it will be created
    data:
        image: bashell/alpine-bash
        container_name: ctr_data
        command: tail -F anything   # .. see above
        volumes:
            - data-vol:/media    # link this ctrs /media dir accessible via a volume named "data-vol"   ... it does exist so the contents will be "copied" to the volume and readable by other ctrs 

volumes:
     data-vol:

docker-compose.yml


#2

Do you mean .circleci/config.yml? Getting the folder name wrong is a fairly common set-up error here :stuck_out_tongue_closed_eyes:


#3

Yes. Thanks. That was a typo. (Ive edited it away now)
But it wasnt connected to my problem.


#4

I don’t use Android, so I can’t answer directly, but you can certainly use Docker Compose inside CircleCI. I wonder if using a lightweight primary build container, with DC pulling in the heavyweight Android images, would be a good approach?

You get more control this way compared to using CircleCI secondary containers (e.g. you can’t docker exec on them as far as I know).


#5

Hi halfer,
and thanks for the feedback.
The fact that im using android should be incidental.

So you mean that there is no simple way to modify the example to use 2 images analogously to the docker-compose setup?
That instead I should run docker (-compose) inside the (circleci standard) docker container?
I presume its a bit tricky saving artifacts (eg build logs etc) from the sub containers then?
I havent worked much with circleci yet, but one of the things I liked is all the clear info you get in the web (browser) interface (almost) for free… “now preforming step …”, “here are the log files etc”
I suspect a lot of this would disappear, and be replaced by a less than helpful “docker-comopse up”?

Is there any simple eg documenting this, and how to do this well/clearly without sacrificing this helpful “meta info”?


#6

It’s difficult for me to say, since it depends what specific thing you believe is analogous, and perhaps also because I’ve not used secondary containers. I use Docker Compose in Docker because that’s how I thought it should be built at the time - I didn’t know about the multi-container system - but my solution turns out to work very well.

I believe that if I now switched back to the CircleCI multi-container system, I’d have less control over the secondary containers, and I would not be able to run my build locally.

Yes. This is known as Docker-in-Docker.

I think it would be easy. You can use docker cp to copy files from a container to the host it runs on. I don’t think you can do that with secondary CircleCI containers (since you do not have access to the host Docker).

That’s a fair point, you would be missing that. However, you can get your containers to report what they are doing, so you may find that in practice, this limitation is quite minor. My use case is a set of browser/integration tests in a micro-service-based system, and the tests are run using PHPUnit. So, my Docker Compose output is my PHPUnit output, including any test failures if applicable. So, I have what I need.


#7

Hello and thanks again for the helpful information.


Just to be sure I understand you can you please clarify what the difference is when you use the terms:

“docker-in docker”, “multi-container”,“secondary container”

Is docker-in-docker not the same as multi-container?
And isnt everything but the “top” container in such a scenario a secondary (or tertiary etc) container?


Im also a bit confused by the apparent contradiction between docker-compose which says:

Then, to activate the Remote Docker Environment, add the setup_remote_docker step
… This step enables you to add docker-compose

And building-docker-images which says:

Note: setup_remote_docker is not currently compatible with the machine executor

So using docker-compose seems to rule out “machine”?

Yet (link as above) docker-compose (sorry i can only post <= 2 properly formatted links) elsewhere says

If you want to use docker compose to manage a multi-container setup with a docker-compose file, use the machine key in your config.yml


So is docker-compose the (only) way to go for file sharing between containers/images? And if so should I be using “machine” or “docker” executor types?


Furthermore whats the point of setup_remote_docker .
Arent docker builds isolated (and ephemeral) by default per definition?

Thanks very much in Advance for any clarification


#8

No. Multi-container, at least in the way I use this phrase, means a way of using several Docker containers side-by-side. This is the normal way of using Docker. The Docker host (under CircleCI control) is likely to be a VM such as VMWare. CircleCI spins up these containers for you, based on your config file.

However, Docker-in-Docker is a special use of Docker where a Docker container is running inside a Docker container. This use case should work, but you should only do this if it makes sense, possibly because Docker containers don’t have access to everything that a VM does, and so (in some cases) they may run into problems when acting as a Docker host.

That all said, I use an official Docker container in CircleCI, and run Docker Compose in there, so this qualifies as Docker-in-Docker and it works very well.

No. If you use Machine, then you are not inside a Docker container, you’re inside a VM. You can do what you like inside this VM, including becoming a Docker host (i.e. running your own Docker Compose).

I think the point of setup_remote_docker is that it sets up a multi-container environment in CircleCI (i.e. so you can use secondary containers). If you are using your own Docker Compose system though, even with the Docker executor, then you’re only using one container (from a CircleCI perspective) and so you don’t need this.

That’s a broad question. If you want to use the CircleCI multi-container system, then your secondary containers will probably be servers (MySQL, Redis, Elasticsearch, etc) and you can contact them from your primary e.g. to run commands/queries. However, yes, I don’t think there is any concept of a shared volume accessible to all of them, since you do not have control of the Docker host that runs these containers (that is under CircleCI control).

So, using Docker Compose will allow you to become a Docker host, and so that would allow you to share files, yes. Volumes between running containers do not work (Docker limitation) but data volumes on volume-only containers does work. I would suggest that you write a proof of concept to get this running - there is much more explanatory power in a small example than lots of theory here :smiley:


#9

Thanks again for the detailed and helpful info.

Just to make sure I understand your closing comments:

Volumes between running containers do not work (Docker limitation).

Not sure I get this. Sharing volumes is possible in docker (and if not when containers were running then there wouldnt be much point). Maybe you meant something different?

volume-only containers does work.

Neither circleci nor docker know if a volume is just being used for data or whatever, so Im not quite sure I understand this either


#10

Some information on Docker volumes in CircleCI’s Docker executor:

Now, I think the limitation comes from the fact that containers are spread over a number of Docker hosts, and volumes do not work over remote connections. I’ve had this problem too, even in Docker Compose, so I wonder whether CircleCI’s underlying Docker system distributes containers over several machines even in a DC system.

However, if you use the Machine executor, you’re on a single VM, and so volumes will work as expected.

Nor me, but this is my experience, with running Docker Compose inside a CircleCI Docker executor.


#11

Thank you very much for all the helpful advice.


#12

No worries, they’re good questions.