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

NixOS: Run Docker containers as declarative systemd services #55179

Merged
merged 12 commits into from Mar 24, 2019

Conversation

benley
Copy link
Member

@benley benley commented Feb 4, 2019

Motivation for this change

https://discourse.nixos.org/t/deploying-docker-containers-declaratively/693

#37553 #26075

Related to #26075 but the implementation is less general; this one just offers an interface to run containers as systemd units from pre-existing Docker images.

cc @copumpkin

TODO:

  • NixOS tests
  • Documentation
  • Environment vars
  • Publishable ports
  • Volume mounts
  • Log driver option, systemd/journald logging integration
  • override UID/GID, workdir, entrypoint, cmd
  • systemd unit generator

@nixos-discourse
Copy link

This pull request has been mentioned on Nix community. There might be relevant details there:

https://discourse.nixos.org/t/deploying-docker-containers-declaratively/693/9

Copy link
Member

@nlewo nlewo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to add a test for this module also.

nixos/modules/virtualisation/docker-containers.nix Outdated Show resolved Hide resolved
nixos/modules/virtualisation/docker-containers.nix Outdated Show resolved Hide resolved
@benley
Copy link
Member Author

benley commented Feb 4, 2019

It would be nice to add a test for this module also.

I absolutely will add tests for this stuff.

@costrouc
Copy link
Member

costrouc commented Feb 4, 2019

Is it too complicated for this PR to address mapping ports as well? Would this require systemd.sockets? I'm thinking with port mapping this PR would cover 90% of all use cases.

@benley
Copy link
Member Author

benley commented Feb 4, 2019

Is it too complicated for this PR to address mapping ports as well? Would this require systemd.sockets? I'm thinking with port mapping this PR would cover 90% of all use cases.

It wouldn't be too hard to handle mapping ports here, as long as we don't try to cover all possible networking setups. I'll have a go at adding it.

@benley
Copy link
Member Author

benley commented Feb 4, 2019

(and no, I don't believe this will require interacting with systemd.sockets)

@benley
Copy link
Member Author

benley commented Feb 4, 2019

I've added support for publishing ports, setting environment variables, and overriding user and workdir.

nixos/modules/virtualisation/docker-containers.nix Outdated Show resolved Hide resolved
nixos/modules/virtualisation/docker-containers.nix Outdated Show resolved Hide resolved
nixos/modules/virtualisation/docker-containers.nix Outdated Show resolved Hide resolved
nixos/modules/virtualisation/docker-containers.nix Outdated Show resolved Hide resolved
@benley

This comment has been minimized.

@expipiplus1
Copy link
Contributor

Looking forward to using this!

I think it would be worthwhile to take a look at this repository: https://github.com/ibuildthecloud/systemd-docker as well as the linked discussions moby/moby#6791 and https://groups.google.com/forum/#!topic/coreos-dev/wf7G6rA7Bf4/discussion

Copy link
Member

@infinisil infinisil left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code looks good to me now (I haven't tested anything though)

@benley benley requested a review from nlewo March 18, 2019 18:22
@tomberek
Copy link
Contributor

Tested. Seems to work well and respond as expected to configuration.nix changes. There are some nuances to deal with like obtaining images (preloader seems difficult to setup), using hostnames or /etc/hosts in containers to avoid hard-coding IPs. Overall, good work! This can serve as a band-aid to deploy applications that are only feasible to run as upstream-provided docker images (or are difficult to port, eg: i got onlyoffice to work with nextcloud using docker-containers).

@danbst danbst merged commit c940053 into NixOS:master Mar 24, 2019
@danbst
Copy link
Contributor

danbst commented Mar 24, 2019

thanks all!

@benley
Copy link
Member Author

benley commented Mar 25, 2019

Woot!

@expipiplus1
Copy link
Contributor

Just checking, but did anyone (@benley, @danbst) take a look at the link I posted: https://github.com/ibuildthecloud/systemd-docker as well as the linked discussions moby/moby#6791 and https://groups.google.com/forum/#!topic/coreos-dev/wf7G6rA7Bf4/discussion

It's not really my area, but I couldn't see any handling of this edge case in this PR

The short of it is that systemd does not actually supervise the Docker container but instead the Docker client. This makes systemd incapable of reliably managing Docker containers without hitting a bunch of really odd situations.

@nyanloutre
Copy link
Member

nyanloutre commented Apr 11, 2019 via email

@benley
Copy link
Member Author

benley commented Apr 11, 2019

Just checking, but did anyone (@benley, @danbst) take a look at the link I posted: https://github.com/ibuildthecloud/systemd-docker as well as the linked discussions moby/moby#6791 and https://groups.google.com/forum/#!topic/coreos-dev/wf7G6rA7Bf4/discussion

It's not really my area, but I couldn't see any handling of this edge case in this PR

The short of it is that systemd does not actually supervise the Docker container but instead the Docker client. This makes systemd incapable of reliably managing Docker containers without hitting a bunch of really odd situations.

Yes, I studied these cases extensively as I was putting this together. The way this is implemented in NixOS, systemd does not attempt to own the container or the processes within it. Instead, it just asks docker to run a thing, keeps it in the foreground, and if the container exits then systemd will know because the docker run command terminates. When systemd wants to stop or restart a container, it also just asks docker to do it with docker stop.

I would love to swap out the implementation at some point to avoid using the Docker daemon, using runc or podman or something like those, and I did try to build this in a way that would make that possible.

@expipiplus1
Copy link
Contributor

@benley great, thanks!

andrew-d pushed a commit to andrew-d/nixpkgs that referenced this pull request May 26, 2019
…5179)

* WIP: Run Docker containers as declarative systemd services

* PR feedback round 1

* docker-containers: add environment, ports, user, workdir options

* docker-containers: log-driver, string->str, line wrapping

* ExecStart instead of script wrapper, %n for container name

* PR feedback: better description and example formatting

* Fix docbook formatting (oops)

* Use a list of strings for ports, expand documentation

* docker-continers: add a simple nixos test

* waitUntilSucceeds to avoid potential weird async issues

* Don't enable docker daemon unless we actually need it

* PR feedback: leave ExecReload undefined

(cherry picked from commit c940053)
andrew-d pushed a commit to andrew-d/nixpkgs that referenced this pull request Dec 9, 2019
…5179)

* WIP: Run Docker containers as declarative systemd services

* PR feedback round 1

* docker-containers: add environment, ports, user, workdir options

* docker-containers: log-driver, string->str, line wrapping

* ExecStart instead of script wrapper, %n for container name

* PR feedback: better description and example formatting

* Fix docbook formatting (oops)

* Use a list of strings for ports, expand documentation

* docker-continers: add a simple nixos test

* waitUntilSucceeds to avoid potential weird async issues

* Don't enable docker daemon unless we actually need it

* PR feedback: leave ExecReload undefined

(cherry picked from commit c940053)
@chrissound
Copy link

chrissound commented Feb 29, 2020

Is there any documentation for this?


Figured it out:

Here is an example:

{ config, pkgs, ... }:

{

  config.docker-containers = {
    hackagecompare = {
      image = "chrissound/hackagecomparestats-webserver:latest";
      ports = ["127.0.0.1:3010:3010"];
      volumes = [
        "/root/hackagecompare/packageStatistics.json:/root/hackagecompare/packageStatistics.json"
      ];
      cmd = [
        "--base-url"
        "\"/hackagecompare\""
      ];
    };
  };
}

And then the usual systemd interface:

journalctl -u docker-hackagecompare.service
systemctl status docker-hackagecompare.service

@expipiplus1
Copy link
Contributor

@chrissound You should consider putting that in the nixos manual.

@fungalcofe
Copy link
Contributor

docker-containers module looks to have been renamed oci-containers and there is now documentation attached.

https://search.nixos.org/options?channel=20.09&from=0&size=30&sort=relevance&query=oci-containers

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