Skip to content

feat: add integrated nice and ionice options for docker#5448

Merged
MichaelEischer merged 6 commits into
restic:masterfrom
ferringb:nice-ionice
Nov 16, 2025
Merged

feat: add integrated nice and ionice options for docker#5448
MichaelEischer merged 6 commits into
restic:masterfrom
ferringb:nice-ionice

Conversation

@ferringb

@ferringb ferringb commented Jul 14, 2025

Copy link
Copy Markdown
Contributor

The intended usage here is to basically kick restic as a background "do it, but don't bother my normal load" process.

This allows passing the following environment variables in to influence scheduling:

  • NICE: usual CPU nice. Defaults to 0.
  • IONICE_CLASS: usual ionice class. Note that setting realtime requires CAP_SYS_ADMIN. Also note the actual ionice default is "none".
  • IONICE_PRIORITY: set the priority within the given class.

What does this PR change? What problem does it solve?

This simplifies setting CPU and IO priority, doing it directly via the container. The expectation is any user of this- as I wished- want to kick restic into the background.

This is possible already with the given containers, however this requires entrypoint override, or manipulating docker CLI args (or k8s args) to achieve it. It's doable, but if the common case is just "do it in the background", providing environment variables to do it is the lowest friction for user.

This integrates 3 environment variables, described above. Further detail:

  • NICE: this is always passed into the nice command, but defaulted to 0- no change.
  • IONICE_CLASS: this is more complex; it's unset. If set, it must be a valid ionice class. Realtime is not supported without the user adding the SYS_NICE capability. I consider that an exceptional case rather than the expected common case of "just background restic". Note also that if the value is unset, we must not touch the class. The default class for processes is "none", but busybox ionice refuses ionice -c0 -nN since a priority for no class makes no sense.
  • IONICE_PRIORITY: if a class is given, this value is honored as an argument to ionice. It defaults to 4- which should be the default priority for any given class.

Was the change previously discussed in an issue or on the forum?

The nice suggestion has appeared in multiple tickets where the end users CPU scheduler was making non-optimal choices; I don't think I've seen the ionice suggestion however.

To my knowledge, there is no explicit asking for integrating controllable nice or ionice however.

Checklist

  • I have added tests for all code changes.
  • I have added documentation for relevant changes (in the manual).
  • There's a new file in changelog/unreleased/ that describes the changes for our users (see template).
  • I'm done! This pull request is ready for review.

@ferringb ferringb marked this pull request as ready for review July 14, 2025 17:19
@ferringb

Copy link
Copy Markdown
Contributor Author

Note: I inlined the nice/ionice into a /bin/sh -c invocation. Yeah, it's mildly dirty; it can be moved into an explicit entrypoint script, I just have a dislike for that approach since they inevitably become overly complex requiring the user to pull the image and extract the entrypoint script to look at it.

Moving that -c blurb into a script would reduce the annoyance of having to escape ", but that's about all it adds. I'll do so if you wish.

Comment thread docker/Dockerfile.release
Comment thread docker/Dockerfile
Comment thread docker/Dockerfile Outdated
Comment thread docker/Dockerfile.release Outdated
Comment thread doc/020_installation.rst Outdated
Comment thread changelog/unreleased/pull-5448 Outdated
@ferringb

ferringb commented Oct 4, 2025

Copy link
Copy Markdown
Contributor Author

cough there's a lot of WTF's in that PR of mine. I'm just going to assume I was half awake at the time. Everything you flagged is valid/correct- pardon.

One thing I do recall- I was wary of CAP_SYS_NICE interaction, specifically if it was dropped, thus the set trickery. Checking the manage page, CAP_SYS_NICE is required to screw with other processes, but isn't required for downgrading the process you're launching- whether ionice or nice. It's only required for increasing the priority. So yeah, lot of WTFs.

ferringb added a commit to ferringb/restic that referenced this pull request Oct 4, 2025
Basically ignore everything that isn't go code.  The core relevance
for this is anyone working on the dockerfiles- adjusting something
like the ENTRYPOINT shouldn't trigger a full rebuild, just that layer,
a gap I noticed while sorting restic#5448.

Note: if restic ever embeds build time files into the binary, this
ignore will have to be updated.

Signed-off-by: Brian Harring <ferringb@gmail.com>
ferringb added a commit to ferringb/restic that referenced this pull request Oct 4, 2025
Basically ignore everything that isn't go code.  The core relevance
for this is anyone working on the dockerfiles- adjusting something
like the ENTRYPOINT shouldn't trigger a full rebuild, just that layer,
a gap I noticed while sorting restic#5448.

Note: if restic ever embeds build time files into the binary, this
ignore will have to be updated.

Signed-off-by: Brian Harring <ferringb@gmail.com>
ferringb added a commit to ferringb/restic that referenced this pull request Oct 4, 2025
Basically ignore everything that isn't go code.  The core relevance
for this is anyone working on the dockerfiles- adjusting something
like the ENTRYPOINT shouldn't trigger a full rebuild, just that layer,
a gap I noticed while sorting restic#5448.

Note: if restic ever embeds build time files into the binary, this
ignore will have to be updated.

Signed-off-by: Brian Harring <ferringb@gmail.com>
@ferringb ferringb mentioned this pull request Oct 4, 2025
4 tasks
ferringb added a commit to ferringb/restic that referenced this pull request Oct 4, 2025
Basically ignore everything that isn't go code.  The core relevance
for this is anyone working on the dockerfiles- adjusting something
like the ENTRYPOINT shouldn't trigger a full rebuild, just that layer,
a gap I noticed while sorting restic#5448.

Note: if restic ever embeds build time files into the binary, this
ignore will have to be updated.

Signed-off-by: Brian Harring <ferringb@gmail.com>

@MichaelEischer MichaelEischer left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I have a few more nits, see suggestions below.

cough there's a lot of WTF's in that PR of mine. I'm just going to assume I was half awake at the time. Everything you flagged is valid/correct- pardon.

No worries, it's the job of a PR review to find those issues

Comment thread docker/Dockerfile Outdated
COPY --from=builder /go/src/github.com/restic/restic/restic /usr/bin

ENTRYPOINT ["/usr/bin/restic"]
# IO class default is "none"- 0, however busybox ionice `-c0 -n<something>`

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
# IO class default is "none"- 0, however busybox ionice `-c0 -n<something>`
# IO class default is "none"- 0, however busybox rejects `ionice -c0 -n<something>`

Comment thread doc/020_installation.rst Outdated
will assign a random hostname each time.

The container additionally honors traditional ``nice`` `(man page) <https://man7.org/linux/man-pages/man1/nice.1.html>`__ and ``ionice`` `(man page) <https://man7.org/linux/man-pages/man1/ionice.1.html#OPTIONS>`__ directives via the following environment variables.
The usage of this is principally to allow restic to be scheduled as a background process reducing latency for the system while running.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
The usage of this is principally to allow restic to be scheduled as a background process reducing latency for the system while running.
This allows restic to be scheduled as a background process to reduce latency for the system while running.

Comment thread doc/020_installation.rst Outdated
Comment on lines +293 to +296
* NICE: If set, this adjusts the CPU prioritization via ``nice -n``. This defaults to no adjustment- standard CPU priority.
* IONICE_CLASS: If set, this adjusts the IO prioritization of the restic process via ``ionice -c`` for the available classes.
Note: if you attempt to set `real-time`, you *will* have to add the ``SYS_NICE`` capability (`see here <https://man7.org/linux/man-pages/man7/capabilities.7.html#DESCRIPTION>`__) to allow assuming this IO class.
* IONICE_PRIORITY: this defaults to 4 (no prioritization or penalties); this is the prioritization within the given `IONICE_CLASS`.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
* NICE: If set, this adjusts the CPU prioritization via ``nice -n``. This defaults to no adjustment- standard CPU priority.
* IONICE_CLASS: If set, this adjusts the IO prioritization of the restic process via ``ionice -c`` for the available classes.
Note: if you attempt to set `real-time`, you *will* have to add the ``SYS_NICE`` capability (`see here <https://man7.org/linux/man-pages/man7/capabilities.7.html#DESCRIPTION>`__) to allow assuming this IO class.
* IONICE_PRIORITY: this defaults to 4 (no prioritization or penalties); this is the prioritization within the given `IONICE_CLASS`.
* ``NICE``: If set, this adjusts the CPU prioritization via ``nice -n``. This defaults to no adjustment- standard CPU priority.
* ``IONICE_CLASS``: If set, this adjusts the IO prioritization of the restic process via ``ionice -c`` for the available classes.
Note: if you attempt to set `real-time`, you *will* have to add the ``SYS_NICE`` capability (`see capabilities manpage <https://man7.org/linux/man-pages/man7/capabilities.7.html#DESCRIPTION>`__) to allow assuming this IO class.
* ``IONICE_PRIORITY``: this defaults to 4 (no prioritization or penalties); this is the prioritization within the given ``IONICE_CLASS``.

@ferringb ferringb Oct 28, 2025

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

For my knowledge- why are you using `` here for literals (NICE for example), but in changelog entries usiong `NICE` ? I thought `` was for commands. Is there something particular to this render pathway?

Comment thread doc/020_installation.rst Outdated
Note: if you attempt to set `real-time`, you *will* have to add the ``SYS_NICE`` capability (`see here <https://man7.org/linux/man-pages/man7/capabilities.7.html#DESCRIPTION>`__) to allow assuming this IO class.
* IONICE_PRIORITY: this defaults to 4 (no prioritization or penalties); this is the prioritization within the given `IONICE_CLASS`.

The following example runs restic such that other CPU and IO requests have higher priority. This effectively perturbs the system as minimally as possible while getting the ``restic`` operation finished.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
The following example runs restic such that other CPU and IO requests have higher priority. This effectively perturbs the system as minimally as possible while getting the ``restic`` operation finished.
The following example runs restic such that other CPU and IO requests have higher priority. This effectively perturbs the system as minimally as possible while ``restic`` runs.

Comment thread docker/Dockerfile.release Outdated
Comment thread changelog/unreleased/pull-5448 Outdated
@@ -0,0 +1,11 @@
Enhancement: Allow nice and ionice configuration for restic containers

ghcr.io/restic/restic containers now support the following environment variables:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
ghcr.io/restic/restic containers now support the following environment variables:
The official restic docker now supports the following environment variables:

Comment thread changelog/unreleased/pull-5448 Outdated
Comment on lines +5 to +7
NICE: set the desired nice scheduling. See `man nice`.
IONICE_CLASS: set the desired I/O scheduling class. See `man ionice`. Note that real time support requires the invoker to manually add the `SYS_ADMIN` capability.
IONICE_PRIORITY: set the prioritization for ionice in the given `IONICE_CLASS`. This does nothing without `IONICE_CLASS`, but defaults to `4` (no priority, no penalties).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
NICE: set the desired nice scheduling. See `man nice`.
IONICE_CLASS: set the desired I/O scheduling class. See `man ionice`. Note that real time support requires the invoker to manually add the `SYS_ADMIN` capability.
IONICE_PRIORITY: set the prioritization for ionice in the given `IONICE_CLASS`. This does nothing without `IONICE_CLASS`, but defaults to `4` (no priority, no penalties).
- `NICE`: set the desired nice scheduling. See `man nice`.
- `IONICE_CLASS`: set the desired I/O scheduling class. See `man ionice`. Note that real time support requires the invoker to manually add the `SYS_ADMIN` capability.
- `IONICE_PRIORITY`: set the prioritization for ionice in the given `IONICE_CLASS`. This does nothing without `IONICE_CLASS`, but defaults to `4` (no priority, no penalties).

Comment thread docker/Dockerfile Outdated
@ferringb

Copy link
Copy Markdown
Contributor Author

All english fixes- which I suggest you reverify, I'm native, but I just don't see that shit- should be resolved. As to the arg passing, as I mentioned, I was using --help so that test was... stupid. To save some time:

main build:

ferringb@hrair ~/restic $ docker/build.sh --no-cache &> /dev/null && echo "built"
built
ferringb@hrair ~/restic $ docker run -e IONICE_CLASS=2 -e IONICE_PRIORITY=7 -e NICE=5 -it docker.io/restic/restic:latest backup
Fatal: nothing to backup, please specify source files/dirs
ferringb@hrair ~/restic $ docker run --entrypoint /bin/sh -e IONICE_CLASS=2 -e IONICE_PRIORITY=7 -e NICE=5 -it docker.io/restic/restic:latest -x /entrypoint.sh backup
+ set -- /usr/bin/restic backup
+ '[' -n 2 ]
+ set -- ionice -c 2 -n 7 /usr/bin/restic backup
+ exec nice -n 5 ionice -c 2 -n 7 /usr/bin/restic backup
Fatal: nothing to backup, please specify source files/dirs

release

ferringb@hrair ~/restic $ docker build -t test -f docker/Dockerfile.release . --no-cache  &> /dev/null && echo "built"
built
ferringb@hrair ~/restic $ docker run -e IONICE_CLASS=2 -e IONICE_PRIORITY=7 -e NICE=5 -it test backup
Fatal: nothing to backup, please specify source files/dirs
ferringb@hrair ~/restic $ docker run --entrypoint /bin/sh -e IONICE_CLASS=2 -e IONICE_PRIORITY=7 -e NICE=5 -it test -x /entrypoint.sh backup
+ set -- /usr/bin/restic backup
+ '[' -n 2 ]
+ set -- ionice -c 2 -n 7 /usr/bin/restic backup
+ exec nice -n 5 ionice -c 2 -n 7 /usr/bin/restic backup
Fatal: nothing to backup, please specify source files/dirs

ferringb and others added 5 commits November 16, 2025 14:15
The intended usage here is to basically kick restic as a background
"do it, but don't bother my normal load" process.

This allows passing the following environment variables in to
influence scheduling:

- NICE: usual CPU nice.  Defaults to 0.  This requires CAP_SYS_NICE
  to set a negative nice (IE, prioritize).
- IONICE_CLASS: usual ionice class.  Note that setting realtime
  requires CAP_SYS_ADMIN.  Also note the actual ionice default
  is "none".
- IONICE_PRIORITY: set the priority within the given class.  Ignored
  if no class is specified due to class default of "no scheduler".

Signed-off-by: Brian Harring <ferringb@gmail.com>

@MichaelEischer MichaelEischer left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM. I've fixed a few more typos, rebased the PR and adjusted the recently added .dockerignore file.

Please take a look.

@ferringb

Copy link
Copy Markdown
Contributor Author

LGTM.

@MichaelEischer MichaelEischer merged commit 87f26ac into restic:master Nov 16, 2025
12 checks passed
kikoqiu pushed a commit to kikoqiu/restic that referenced this pull request Nov 26, 2025
The intended usage here is to basically kick restic as a background
"do it, but don't bother my normal load" process.

This allows passing the following environment variables in to
influence scheduling:

- NICE: usual CPU nice.  Defaults to 0.  This requires CAP_SYS_NICE
  to set a negative nice (IE, prioritize).
- IONICE_CLASS: usual ionice class.  Note that setting realtime
  requires CAP_SYS_ADMIN.  Also note the actual ionice default
  is "none".
- IONICE_PRIORITY: set the priority within the given class.  Ignored
  if no class is specified due to class default of "no scheduler".

---------

Signed-off-by: Brian Harring <ferringb@gmail.com>
Co-authored-by: Michael Eischer <michael.eischer@fau.de>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants