{"id":294,"date":"2016-09-19T12:39:12","date_gmt":"2016-09-19T20:39:12","guid":{"rendered":"http:\/\/www.nathanbak.com\/?p=294"},"modified":"2026-01-02T20:04:41","modified_gmt":"2026-01-03T04:04:41","slug":"running-a-docker-container-when-the-machine-starts","status":"publish","type":"post","link":"https:\/\/nathanbak.com\/?p=294","title":{"rendered":"Running a Docker container when the machine starts"},"content":{"rendered":"<p>Normally when I have a Docker container that I want to automatically come up whenever the machine restarts, I simply use <a href=\"https:\/\/docs.docker.com\/engine\/reference\/run\/#restart-policies-restart\">&#8211;restart=always<\/a> when running the container (or &#8220;restart: always&#8221; in a Docker Compose YAML file).\u00a0 Recently encountered a situation where that didn&#8217;t meet my needs.\u00a0 I thought it would be quick and easy to start the container from a service (a la systemd).\u00a0 It ended up being easy, but it wasn&#8217;t as quick as I thought because I made some incorrect assumptions and sloppy mistakes along the way&#8211;so in case I need to do this again I am documenting what I did here . . .<\/p>\n<p>I was using an Ubuntu 16.04 machine and for my example I&#8217;m using my <a href=\"https:\/\/hub.docker.com\/r\/bakchoy\/beavertonschoolcalendar\/\">Beaverton School District Calendar image<\/a>.\u00a0 To create the actual service, I created the file \/etc\/systemd\/system\/schoolCal.service with the contents:<\/p>\n<pre>[Unit]\r\nDescription=School Calendar Service\r\nRequires=docker.service\r\nAfter=docker.service\r\n\r\n[Service]\r\nRestart=always\r\nExecStart=\/etc\/systemd\/system\/schoolCal.sh\r\n\r\n[Install]\r\nWantedBy=multi-user.target<\/pre>\n<p>There&#8217;s nothing special about the service definition, it basically runs the schoolCal.sh script.\u00a0 The problem I encountered when creating the service file was I forgot to add the dependency on the docker.service (I&#8217;m not sure if both &#8220;Requires&#8221; and &#8220;After&#8221; need to be set, but at least one of them does).\u00a0 To enable the service I ran:<\/p>\n<pre>sudo systemctl enable schoolCal<\/pre>\n<p>Here are the contents of the schoolCal.sh script:<\/p>\n<pre>#!\/bin\/sh\r\ndocker pull bakchoy\/beavertonschoolcalendar\r\ndocker run -i --net host -p 9999:9999 bakchoy\/beavertonschoolcalendar<\/pre>\n<p>The script is very simple, but it took several tries for me to get it right.\u00a0 Here are some details I encountered\/considered:<\/p>\n<ul>\n<li>It&#8217;s necessary to make the script executable<\/li>\n<li>The explicit pull means that the latest image will always be used when starting up a new container.<\/li>\n<li>Since I want the container log to be available via journalctl, the container has to be run in interactive mode &#8220;-i&#8221; instead of in detached mode.<\/li>\n<li>Normally when I run stuff in interactive mode, I use &#8220;-i -t&#8221;.\u00a0 When I had that, the script worked fine when I ran it manually, but when invoked by the service it would fail with &#8220;the input device is not a TTY&#8221;.\u00a0 It took me awhile to figure out the fix was simply to remove the &#8220;-t&#8221;.<\/li>\n<li>In this case, I wanted the container ip\/hostname to be the same as the host, so I set &#8220;&#8211;net host&#8221;.\u00a0 In most situations that probably isn&#8217;t necessary.<\/li>\n<li>Space isn&#8217;t an issue here and I have a different mechanism for cleaning old containers.\u00a0 Otherwise I might have added a &#8220;-rm&#8221; (but I&#8217;m not certain it would work as expected).<\/li>\n<\/ul>\n<p>I found <a href=\"https:\/\/docs.docker.com\/engine\/admin\/host_integration\/\">https:\/\/docs.docker.com\/engine\/admin\/host_integration\/<\/a> which also has an example invoking a Docker container via systemd (and upstart), but it seems closer to using a Docker restart policy than what I&#8217;m doing.\u00a0 Although in general I think using the built-in Docker restart policies is a better approach, here are some aspects that differentiate my approach:<\/p>\n<ul>\n<li>No specific container tied to the service&#8211;a container doesn&#8217;t need to exist for things to work when the service is started<\/li>\n<li>I pull request can be included to basically provide automatic updates<\/li>\n<li>Logging can be directed to the standard service logging mechanism (such as journalctl)<\/li>\n<li>The service can be monitored with the same tools for monitoring other services rather than Docker way<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Normally when I have a Docker container that I want to automatically come up whenever the machine restarts, I simply use &#8211;restart=always when running the container (or &#8220;restart: always&#8221; in a Docker Compose YAML file).\u00a0 Recently encountered a situation where that didn&#8217;t meet my needs.\u00a0 I thought it would be quick and easy to start &hellip; <a href=\"https:\/\/nathanbak.com\/?p=294\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Running a Docker container when the machine starts&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[8],"class_list":["post-294","post","type-post","status-publish","format-standard","hentry","category-uncategorized","tag-docker"],"_links":{"self":[{"href":"https:\/\/nathanbak.com\/index.php?rest_route=\/wp\/v2\/posts\/294","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nathanbak.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nathanbak.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nathanbak.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nathanbak.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=294"}],"version-history":[{"count":3,"href":"https:\/\/nathanbak.com\/index.php?rest_route=\/wp\/v2\/posts\/294\/revisions"}],"predecessor-version":[{"id":395,"href":"https:\/\/nathanbak.com\/index.php?rest_route=\/wp\/v2\/posts\/294\/revisions\/395"}],"wp:attachment":[{"href":"https:\/\/nathanbak.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=294"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nathanbak.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=294"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nathanbak.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=294"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}