Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docker.nix: Add options for named volumes and networks #64580

Closed
wants to merge 1 commit into from

Conversation

mkaito
Copy link
Contributor

@mkaito mkaito commented Jul 10, 2019

Motivation for this change

I was porting some docker-compose stuff to docker-containers.nix and found the lack of declarative networks and volumes.

Things done
  • Added options:
    • services.docker.volumes = [ "one" "two" ];
    • services.docker.networks.foo = {};
  • Added tests

A few notes:

  • Code runs in a docker.service postStart, since I didn't want to tie it to any particular way to run docker containers, plus these entities are "docker-global", and so I think they fit well in the docker module.
  • This is probably incompatible with imperative creation of volumes and networks. The code removes any named volumes and networks other than the default ones and the ones declared in the module.
  • The "remove unnecessary things" code is a little more complex than I had hoped for. At least, turns out you can just use grep to do a set complement, which is nice.
  • I have never written any nixos tests before, I'm not sure if the way I test for entity removal is the way to go here; feedback is most welcome.
  • nix-build -A nixosTests.docker passes on my computer.
  • Tested using sandboxing (nix.useSandbox on NixOS, or option sandbox in nix.conf on non-NixOS)
  • Built on platform(s)
    • NixOS
    • macOS
    • other Linux distributions
  • Tested via one or more NixOS test(s) if existing and applicable for the change (look inside nixos/tests)
  • Tested compilation of all pkgs that depend on this change using nix-shell -p nix-review --run "nix-review wip"
  • Tested execution of all binary files (usually in ./result/bin/)
  • Determined the impact on package closure size (by running nix path-info -S before and after)
  • Ensured that relevant documentation is up to date
  • Fits CONTRIBUTING.md.

@mkaito
Copy link
Contributor Author

mkaito commented Jul 10, 2019

@grahamc would you like to have a look?

@yorickvP
Copy link
Contributor

@GrahamcOfBorg test docker

@yorickvP
Copy link
Contributor

cc:@offlinehacker

@mkaito mkaito force-pushed the mkaito/docker-volumes-networks branch from 492372c to 2966b65 Compare July 11, 2019 14:42
@mkaito
Copy link
Contributor Author

mkaito commented Jul 11, 2019

I've added some || true at the end of the docker {volume,network} rm lines, so that failing to delete a volume or network (presumably because they are in use) does not prevent the docker unit from starting.

I ran into this with gitlab-runner. The helper image it uses to handle shared operations, and specifically the handling of shared cache, creates an anonymous volume which my changes to the docker module will try (and fail) to delete.

@offlinehacker
Copy link
Contributor

I'm unsure about these abstractions being in docker.nix file. Can we split into two files, one only managing docker service, and other managing these additional abstractions over networking and volumes. It's just for sake of having clear boundaries defined, so refactoring and testing is easier.

@offlinehacker
Copy link
Contributor

offlinehacker commented Jul 13, 2019

I would also have a separate systemd unit and not as part of docker postStart, that will separate systemd units in clear way and makes debugging easier.

@mkaito
Copy link
Contributor Author

mkaito commented Jul 16, 2019

That seems over-engineered to me, but thanks for the review.

@offlinehacker
Copy link
Contributor

offlinehacker commented Jul 17, 2019

I think it does not change a lot in terms of additonal complexity, but provides a separation between what is a basically systemd unit for docker and all our custom abstraction over it.

The problem is that nixos is already bloated from my point of view, and especially nixpkgs and I'm not against additional abstraction, especially if it provides value to multiple users. Let's just keep it separated, so in the future it can be easier to refactor, does this makes sense?

@mkaito
Copy link
Contributor Author

mkaito commented Jul 17, 2019

The other option I was considering is making it easier to run some preStart in docker-containers.nix, which would probably also work. You could just run some docker volume create foo || true in there.

I wrote this PR hoping to improve the nix wrappers around Docker, and I have some patches for the other module down here that I need to clean up for review too.

I also realize that trying to make Docker be actually nix-compliant is a fool's errand, so maybe this entire PR is just misled.

@grahamc
Copy link
Member

grahamc commented Jul 17, 2019

(I know @offlinehacker already gave some feedback, just wanting to officially delegate my opinion to him -- as @mkaito requested my review on IRC.)

@Lucus16
Copy link
Contributor

Lucus16 commented Jul 19, 2019

This is probably incompatible with imperative creation of volumes and networks.

For compatibility, it's probably best to introduce something similar to users.mutableUsers so imperatively created volumes and networks aren't deleted unless mutability is explicitly disabled. If keeping track of which volumes and networks were created by nix is too much effort, it's possible to disable the volumes and networks options entirely when they're not explicitly enabled.

I think it's bad if whether the docker daemon comes up depends on whether applying these new options fails, but I also think user services may need to depend on these volumes and networks being created, so I agree that it's best if they're handled in a separate systemd unit.

At least, turns out you can just use grep to do a set complement, which is nice.

There's comm in coreutils which was made for set complements.

@mkaito
Copy link
Contributor Author

mkaito commented Jul 21, 2019

This is probably incompatible with imperative creation of volumes and networks.

For compatibility, it's probably best to introduce something similar to users.mutableUsers so imperatively created volumes and networks aren't deleted unless mutability is explicitly disabled. If keeping track of which volumes and networks were created by nix is too much effort, it's possible to disable the volumes and networks options entirely when they're not explicitly enabled.

You can't delete used volumes either way. For example, gitlab-runner's docker runner uses an implicit container that handles things like cache sharing and artifact upload. It defines a dynamic volume, which we can not delete because the container is always running when gitlab-runner is. We also can't add it to the set of declarative volumes, because it's not a named volume. This is actually the reason I added || true to all the deletion incantations.

We can create a custom helper image, but that seems like three kinds of overkill to me, and just adds unnecessary maintenance burden.

Trying to make the Docker world deterministic is a bit of a fool's errand.

Perhaps the best idea here is to either call it ensureVolumes and ensureNetwork, or just drop this idea and put some create volume foo in a preStart.

I have some patches to docker-containers.nix, and there's something to be said about putting all this over there.

At least, turns out you can just use grep to do a set complement, which is nice.

There's comm in coreutils which was made for set complements.

Yeah, I saw comm in some of the snippets. Would you say using comm is preferrable here? I didn't find comm -23 <(A) <(B) any more readable or intuitive than some magic grep incantation.

@stale
Copy link

stale bot commented Jun 1, 2020

Thank you for your contributions.
This has been automatically marked as stale because it has had no activity for 180 days.
If this is still important to you, we ask that you leave a comment below. Your comment can be as simple as "still important to me". This lets people see that at least one person still cares about this. Someone will have to do this at most twice a year if there is no other activity.
Here are suggestions that might help resolve this more quickly:

  1. Search for maintainers and people that previously touched the
    related code and @ mention them in a comment.
  2. Ask on the NixOS Discourse. 3. Ask on the #nixos channel on
    irc.freenode.net.

@stale stale bot added the 2.status: stale https://github.com/NixOS/nixpkgs/blob/master/.github/STALE-BOT.md label Jun 1, 2020
@mkaito mkaito closed this Jun 2, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants