{"id":13552437,"url":"https://github.com/cturra/docker-ntp","last_synced_at":"2025-04-03T03:31:38.078Z","repository":{"id":27588594,"uuid":"103866454","full_name":"cturra/docker-ntp","owner":"cturra","description":"🕒 Chrony NTP Server running in a Docker container (without the priviledged flag) ","archived":false,"fork":false,"pushed_at":"2025-03-16T19:47:38.000Z","size":63,"stargazers_count":385,"open_issues_count":9,"forks_count":137,"subscribers_count":12,"default_branch":"main","last_synced_at":"2025-03-16T20:35:51.023Z","etag":null,"topics":["alpine-linux","chrony","chronyd","docker","ntp","ntp-server","ntpd"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cturra.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-09-17T22:28:23.000Z","updated_at":"2025-03-16T19:47:38.000Z","dependencies_parsed_at":"2023-02-15T00:20:56.294Z","dependency_job_id":"a232ebcf-a665-404c-a2c3-827068c0dd1e","html_url":"https://github.com/cturra/docker-ntp","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cturra%2Fdocker-ntp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cturra%2Fdocker-ntp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cturra%2Fdocker-ntp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cturra%2Fdocker-ntp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cturra","download_url":"https://codeload.github.com/cturra/docker-ntp/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246933435,"owners_count":20857048,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["alpine-linux","chrony","chronyd","docker","ntp","ntp-server","ntpd"],"created_at":"2024-08-01T12:02:03.983Z","updated_at":"2025-04-03T03:31:33.015Z","avatar_url":"https://github.com/cturra.png","language":"Shell","funding_links":["https://www.buymeacoffee.com/cturra"],"categories":["Shell"],"sub_categories":[],"readme":"## About this container\n\n[![Docker Pulls](https://img.shields.io/docker/pulls/cturra/ntp.svg?logo=docker\u0026label=pulls\u0026style=for-the-badge\u0026color=0099ff\u0026logoColor=ffffff)](https://hub.docker.com/r/cturra/ntp/)\n[![Docker Stars](https://img.shields.io/docker/stars/cturra/ntp.svg?logo=docker\u0026label=stars\u0026style=for-the-badge\u0026color=0099ff\u0026logoColor=ffffff)](https://hub.docker.com/r/cturra/ntp/)\n[![GitHub Stars](https://img.shields.io/github/stars/cturra/docker-ntp.svg?logo=github\u0026label=stars\u0026style=for-the-badge\u0026color=0099ff\u0026logoColor=ffffff)](https://github.com/cturra/docker-ntp)\n[![Apache licensed](https://img.shields.io/badge/license-Apache-blue.svg?logo=apache\u0026style=for-the-badge\u0026color=0099ff\u0026logoColor=ffffff)](https://raw.githubusercontent.com/cturra/docker-ntp/master/LICENSE)\n\nThis container runs [chrony](https://chrony-project.org/) on [Alpine Linux](https://alpinelinux.org/).\n\n[chrony](https://chrony-project.org/) is a versatile implementation of the Network Time Protocol (NTP). It can synchronise the system clock with NTP servers, reference clocks (e.g. GPS receiver), and manual input using wristwatch and keyboard. It can also operate as an NTPv4 (RFC 5905) server and peer to provide a time service to other computers in the network.\n\n\n## Supported Architectures\n\nArchitectures officially supported by this Docker container. Simply pulling this container from [Docker Hub](https://hub.docker.com/r/cturra/ntp) should retrieve the correct image for your architecture.\n\n![Linux x86-64](https://img.shields.io/badge/linux/amd64-green?style=flat-square)\n![ARMv8 64-bit](https://img.shields.io/badge/linux/arm64-green?style=flat-square)\n![IBM POWER8](https://img.shields.io/badge/linux/ppc64le-green?style=flat-square)\n![IBM Z Systems](https://img.shields.io/badge/linux/s390x-green?style=flat-square)\n![Linux x86/i686](https://img.shields.io/badge/linux/386-green?style=flat-squareg)\n![ARMv7 32-bit](https://img.shields.io/badge/linux/arm/v7-green?style=flat-square)\n![ARMv6 32-bit](https://img.shields.io/badge/linux/arm/v6-green?style=flat-square)\n\n\n## How to Run this container\n\n### With the Docker CLI\n\nPull and run -- it's this simple.\n\n```\n# pull from docker hub\n$\u003e docker pull cturra/ntp\n\n# run ntp\n$\u003e docker run --name=ntp            \\\n              --restart=always      \\\n              --detach              \\\n              --publish=123:123/udp \\\n              cturra/ntp\n\n# OR run ntp with higher security\n$\u003e docker run --name=ntp                           \\\n              --restart=always                     \\\n              --detach                             \\\n              --publish=123:123/udp                \\\n              --read-only                          \\\n              --tmpfs=/etc/chrony:rw,mode=1750     \\\n              --tmpfs=/run/chrony:rw,mode=1750     \\\n              --tmpfs=/var/lib/chrony:rw,mode=1750 \\\n              cturra/ntp\n```\n\n\n### With Docker Compose\n\nUsing the docker-compose.yml file included in this git repo, you can build the container yourself (should you choose to).\n*Note: this docker-compose files uses the `3.9` compose format, which requires Docker Engine release 19.03.0+\n\n```\n# run ntp\n$\u003e docker compose up -d ntp\n\n# (optional) check the ntp logs\n$\u003e docker compose logs ntp\n```\n\n\n### With Docker Swarm\n\n*(These instructions assume you already have a swarm)*\n\n```\n# deploy ntp stack to the swarm\n$\u003e docker stack deploy -c docker-compose.yml cturra\n\n# check that service is running\n$\u003e docker stack services cturra\n\n# (optional) view the ntp logs\n$\u003e docker service logs -f cturra_ntp\n```\n\n\n### From a Local command line\n\nUsing the vars file in this git repo, you can update any of the variables to reflect your\nenvironment. Once updated, simply execute the build then run scripts.\n\n```\n# build ntp\n$\u003e ./build.sh\n\n# run ntp\n$\u003e ./run.sh\n```\n\n\n## Configure NTP Servers\n\nBy default, this container uses CloudFlare's time server (time.cloudflare.com). If you'd\nlike to use one or more different NTP server(s), you can pass this container an `NTP_SERVERS`\nenvironment variable. This can be done by updating the [vars](vars), [docker-compose.yml](docker-compose.yml)\nfiles or manually passing `--env=NTP_SERVERS=\"...\"` to `docker run`.\n\nBelow are some examples of how to configure common NTP Servers.\n\nDo note, to configure more than one server, you must use a comma delimited list WITHOUT spaces.\n\n```\n# (default) cloudflare\nNTP_SERVERS=\"time.cloudflare.com\"\n\n# google\nNTP_SERVERS=\"time1.google.com,time2.google.com,time3.google.com,time4.google.com\"\n\n# alibaba\nNTP_SERVERS=\"ntp1.aliyun.com,ntp2.aliyun.com,ntp3.aliyun.com,ntp4.aliyun.com\"\n\n# local (offline)\nNTP_SERVERS=\"127.127.1.1\"\n```\n\nIf you're interested in a public list of stratum 1 servers, you can have a look at the following list.\nDo make sure to verify the ntp server is active as this list does appaer to have some no longer active\nservers.\n\n * https://www.advtimesync.com/docs/manual/stratum1.html\n\n\n## Chronyd Options\n\n### No Client Log (noclientlog)\n\nThis is optional and not enabled by default. If you provide the `NOCLIENTLOG=true` envivonrment variable,\nchrony will be configured to:\n\n\u003e Specifies that client accesses are not to be logged. Normally they are logged, allowing statistics to\n\u003e be reported using the clients command in chronyc. This option also effectively disables server support\n\u003e for the NTP interleaved mode.\n\n\n## Logging\n\nBy default, this project logs informational messages to stdout, which can be helpful when running the\nntp service. If you'd like to change the level of log verbosity, pass the `LOG_LEVEL` environment\nvariable to the container, specifying the level (`#`) when you first start it. This option matches\nthe chrony `-L` option, which support the following levels can to specified: 0 (informational), 1\n(warning), 2 (non-fatal error), and 3 (fatal error).\n\nFeel free to check out the project documentation for more information at:\n\n * https://chrony-project.org/documentation.html\n\n\n## Setting your timezone\n\nBy default the UTC timezone is used, however if you'd like to adjust your NTP server to be running in your\nlocal timezone, all you need to do is provide a `TZ` environment variable following the standard TZ data format.\nAs an example, using `docker-compose.yaml`, that would look like this if you were located in Vancouver, Canada:\n\n```yaml\n  ...\n  environment:\n    - TZ=America/Vancouver\n    ...\n```\n\n\n## Enable Network Time Security\n\nIf **all** the `NTP_SERVERS` you have configured support NTS (Network Time Security) you can pass the `ENABLE_NTS=true`\noption to the container to enable it. As an example, using `docker-compose.yaml`, that would look like this:\n\n```yaml\n  ...\n  environment:\n    - NTP_SERVER=time.cloudflare.com\n    - ENABLE_NTS=true\n    ...\n```\n\nIf any of the `NTP_SERVERS` you have configured does not support NTS, you will see a message like the\nfollowing during startup:\n\n\u003e NTS-KE session with 164.67.62.194:4460 (tick.ucla.edu) timed out\n\n\n## Testing your NTP Container\n\nFrom any machine that has `ntpdate` you can query your new NTP container with the follow\ncommand:\n\n```\n$\u003e ntpdate -q \u003cDOCKER_HOST_IP\u003e\n```\n\n\nHere is a sample output from my environment:\n\n```\n$\u003e ntpdate -q 10.13.13.9\nserver 10.13.1.109, stratum 4, offset 0.000642, delay 0.02805\n14 Mar 19:21:29 ntpdate[26834]: adjust time server 10.13.13.109 offset 0.000642 sec\n```\n\n\nIf you see a message, like the following, it's likely the clock is not yet synchronized.\nYou should see this go away if you wait a bit longer and query again.\n```\n$\u003e ntpdate -q 10.13.13.9\nserver 10.13.13.9, stratum 16, offset 0.005689, delay 0.02837\n11 Dec 09:47:53 ntpdate[26030]: no server suitable for synchronization found\n```\n\nTo see details on the ntp status of your container, you can check with the command below\non your docker host:\n```\n$\u003e docker exec ntp chronyc tracking\nReference ID    : D8EF2300 (time1.google.com)\nStratum         : 2\nRef time (UTC)  : Sun Mar 15 04:33:30 2020\nSystem time     : 0.000054161 seconds slow of NTP time\nLast offset     : -0.000015060 seconds\nRMS offset      : 0.000206534 seconds\nFrequency       : 5.626 ppm fast\nResidual freq   : -0.001 ppm\nSkew            : 0.118 ppm\nRoot delay      : 0.022015510 seconds\nRoot dispersion : 0.001476757 seconds\nUpdate interval : 1025.2 seconds\nLeap status     : Normal\n```\n\n\nHere is how you can see a peer list to verify the state of each ntp source configured:\n```\n$\u003e docker exec ntp chronyc sources\n210 Number of sources = 2\nMS Name/IP address         Stratum Poll Reach LastRx Last sample\n===============================================================================\n^+ time.cloudflare.com           3  10   377   404   -623us[ -623us] +/-   24ms\n^* time1.google.com              1  10   377  1023   +259us[ +244us] +/-   11ms\n```\n\n\nFinally, if you'd like to see statistics about the collected measurements of each ntp\nsource configured:\n```\n$\u003e docker exec ntp chronyc sourcestats\n210 Number of sources = 2\nName/IP Address            NP  NR  Span  Frequency  Freq Skew  Offset  Std Dev\n==============================================================================\ntime.cloudflare.com        35  18  139m     +0.014      0.141   -662us   530us\ntime1.google.com           33  13  128m     -0.007      0.138   +318us   460us\n```\n\n\nAre you seeing messages like these and wondering what is going on?\n```\n$ docker logs -f ntps\n[...]\n2021-05-25T18:41:40Z System clock wrong by -2.535004 seconds\n2021-05-25T18:41:40Z Could not step system clock\n2021-05-25T18:42:47Z System clock wrong by -2.541034 seconds\n2021-05-25T18:42:47Z Could not step system clock\n```\n\nGood question! Since `chronyd` is running with the `-x` flag, it will not try to control\nthe system (container host) clock. This of course is necessary because the process does not\nhave priviledge (for good reason) to modify the clock on the system.\n\nLike any host on your network, simply use your preferred ntp client to pull the time from\nthe running ntp container on your container host.\n\n---\n\u003ca href=\"https://www.buymeacoffee.com/cturra\" target=\"_blank\"\u003e\u003cimg src=\"https://cdn.buymeacoffee.com/buttons/default-yellow.png\" alt=\"Buy Me A Coffee\" height=\"41\" width=\"174\"\u003e\u003c/a\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcturra%2Fdocker-ntp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcturra%2Fdocker-ntp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcturra%2Fdocker-ntp/lists"}