{"id":13041,"date":"2026-09-16T07:35:00","date_gmt":"2026-09-16T05:35:00","guid":{"rendered":"https:\/\/www.lukaswojcik.com\/blog\/?p=13041"},"modified":"2026-10-26T12:07:07","modified_gmt":"2026-10-26T11:07:07","slug":"tutorial-hardening-a-docker-compose-file-for-unattended-operation-on-a-raspberry-pi","status":"publish","type":"post","link":"https:\/\/www.lukaswojcik.com\/blog\/en\/raspberry-pi\/tutorials-en-raspberry-pi\/tutorial-hardening-a-docker-compose-file-for-unattended-operation-on-a-raspberry-pi\/","title":{"rendered":"Tutorial: Hardening a Docker Compose File for Unattended Operation on a Raspberry Pi"},"content":{"rendered":"<p>A Docker Compose file can reduce common operating risks, but a few settings do not guarantee a year of unattended service. Restart behavior, health reporting, log retention, resource limits and image updates solve different problems. Backups, monitoring and tested recovery remain separate requirements.<\/p>\n<figure class=\"lw-diagram\"><img loading=\"lazy\" decoding=\"async\" src=\"\/blog\/wp-content\/uploads\/diagrams\/dia-13041-composehard-20261024.png\" alt=\"Four complementary checks for Compose operation: restart behavior, health reporting, resource budgets and image recovery. Configuration validation alone does not verify recovery.\" width=\"1120\" height=\"580\"><figcaption>Four complementary checks for Compose operation: restart behavior, health reporting, resource budgets and image recovery. Configuration validation alone does not verify recovery.<\/figcaption><\/figure>\n<h2>A starting point for a long-running application<\/h2>\n<p>The following example targets a Linux Docker Engine with current Compose. The application image must support UID\/GID 1000, a read-only root filesystem and the specified health endpoint, and must contain curl. UID and GID are the numeric user and group identifiers used for file permissions. The image reference comes from APP_IMAGE and must include a verified digest. The resource values are illustrative, not sizing recommendations for every Raspberry Pi.<\/p>\n<figure style=\"--cbb-digits:2\" class=\"cbb cbb--wrap cbb--numbers wp-block-code-beautifier-block-code\" data-lang=\"yaml\"><figcaption class=\"cbb-head\"><span class=\"cbb-lang\">YAML<\/span><span class=\"cbb-actions\"><button type=\"button\" class=\"cbb-button cbb-button--wrap\" data-cbb-action=\"wrap\" aria-pressed=\"true\" title=\"Wrap long lines\"><svg aria-hidden=\"true\" focusable=\"false\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"><path d=\"M2 4h12M2 8h9.5a2.5 2.5 0 0 1 0 5H8m0 0 1.5-1.5M8 13l1.5 1.5M2 12h3\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/><\/svg><span class=\"cbb-sr\">Wrap long lines<\/span><\/button><button type=\"button\" class=\"cbb-button cbb-button--copy\" data-cbb-action=\"copy\" data-cbb-done=\"Copied\" data-cbb-failed=\"Press Ctrl+C to copy\"><svg aria-hidden=\"true\" focusable=\"false\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"><rect x=\"5.5\" y=\"5.5\" width=\"8\" height=\"8.5\" rx=\"1.5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"\/><path d=\"M10.5 3.5V3A1.5 1.5 0 0 0 9 1.5H4A1.5 1.5 0 0 0 2.5 3v6.5A1.5 1.5 0 0 0 4 11h.5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"\/><\/svg><span class=\"cbb-button-label\" aria-live=\"polite\">Copy<\/span><\/button><\/span><\/figcaption><pre class=\"cbb-pre\" tabindex=\"0\"><code class=\"cbb-code language-yaml\" style=\"counter-reset:cbb-line 0;\"><span class=\"cbb-line\"><span class=\"cbb-attr\">services<\/span>:\n<\/span><span class=\"cbb-line\">  <span class=\"cbb-attr\">app<\/span>:\n<\/span><span class=\"cbb-line\">    <span class=\"cbb-attr\">image<\/span>: <span class=\"cbb-string\">\"${APP_IMAGE:?verified image reference required}\"<\/span>\n<\/span><span class=\"cbb-line\">    <span class=\"cbb-attr\">restart<\/span>: unless-stopped\n<\/span><span class=\"cbb-line\">    <span class=\"cbb-attr\">healthcheck<\/span>:\n<\/span><span class=\"cbb-line\">      <span class=\"cbb-attr\">test<\/span>: &#91;<span class=\"cbb-string\">\"CMD\"<\/span>, <span class=\"cbb-string\">\"curl\"<\/span>, <span class=\"cbb-string\">\"-fsS\"<\/span>, <span class=\"cbb-string\">\"--max-time\"<\/span>, <span class=\"cbb-string\">\"4\"<\/span>, <span class=\"cbb-string\">\"http:\/\/localhost:8080\/health\"<\/span>&#93;\n<\/span><span class=\"cbb-line\">      <span class=\"cbb-attr\">interval<\/span>: 30s\n<\/span><span class=\"cbb-line\">      <span class=\"cbb-attr\">timeout<\/span>: 5s\n<\/span><span class=\"cbb-line\">      <span class=\"cbb-attr\">retries<\/span>: <span class=\"cbb-number\">3<\/span>\n<\/span><span class=\"cbb-line\">      <span class=\"cbb-attr\">start_period<\/span>: 60s\n<\/span><span class=\"cbb-line\">    <span class=\"cbb-attr\">logging<\/span>:\n<\/span><span class=\"cbb-line\">      <span class=\"cbb-attr\">driver<\/span>: json-file\n<\/span><span class=\"cbb-line\">      <span class=\"cbb-attr\">options<\/span>:\n<\/span><span class=\"cbb-line\">        <span class=\"cbb-attr\">max-size<\/span>: <span class=\"cbb-string\">\"10m\"<\/span>\n<\/span><span class=\"cbb-line\">        <span class=\"cbb-attr\">max-file<\/span>: <span class=\"cbb-string\">\"3\"<\/span>\n<\/span><span class=\"cbb-line\">    <span class=\"cbb-attr\">mem_limit<\/span>: 512m\n<\/span><span class=\"cbb-line\">    <span class=\"cbb-attr\">cpus<\/span>: <span class=\"cbb-number\">1.5<\/span>\n<\/span><span class=\"cbb-line\">    <span class=\"cbb-attr\">pids_limit<\/span>: <span class=\"cbb-number\">128<\/span>\n<\/span><span class=\"cbb-line\">    <span class=\"cbb-attr\">read_only<\/span>: <span class=\"cbb-constant\">true<\/span>\n<\/span><span class=\"cbb-line\">    <span class=\"cbb-attr\">tmpfs<\/span>:\n<\/span><span class=\"cbb-line\">      <span class=\"cbb-operator\">-<\/span> \/tmp:size=64m,mode=1777\n<\/span><span class=\"cbb-line\">    <span class=\"cbb-attr\">security_opt<\/span>:\n<\/span><span class=\"cbb-line\">      <span class=\"cbb-operator\">-<\/span> no-new-privileges:true\n<\/span><span class=\"cbb-line\">    <span class=\"cbb-attr\">user<\/span>: <span class=\"cbb-string\">\"1000:1000\"<\/span><\/span><\/code><\/pre><\/figure>\n<p>The image\u2019s required data directories need explicit writable volumes or bind mounts. A volume is storage managed by Docker; a bind mount makes a chosen host directory available inside the container. The example deliberately contains no database or persistent application data. A service that needs different permissions, ports, temporary directories or resources requires a corresponding configuration; copying these settings into an arbitrary image is not sufficient.<\/p>\n<h2>Restarting and reporting health<\/h2>\n<p><code>unless-stopped<\/code> restarts a terminated long-running container according to Docker\u2019s policy while preserving an intentional stop across daemon restarts. With <code>always<\/code>, a manually stopped container can return after the daemon restarts; it does not immediately restart merely because the stop command completed. The default <code>no<\/code> disables automatic restarting. One-shot jobs may legitimately use a different policy.<\/p>\n<p>A restart policy does not restart a process merely because the container is unhealthy. In ordinary Compose operation, a healthcheck records status; recovery needs an application exit or a separately designed controller. Backoff means increasing the wait between restart attempts. This reduces restart frequency but does not eliminate resource consumption or replace an alert.<\/p>\n<p>The example probes an application-specific endpoint inside the container. A missing curl executable, wrong URL, failed dependency or slow response can all produce unhealthy status; that status does not uniquely diagnose a hang. A readiness check may include essential dependencies, while an automatic restart decision needs care to avoid restarting every service during a shared database outage.<\/p>\n<p><code>start_period<\/code> allows startup failures without immediately counting them toward the retry threshold. A successful probe during that period ends this grace behavior for subsequent failures. Probe duration and scheduling also affect timing, so three retries at 30-second intervals are not an exact 90-second startup allowance.<\/p>\n<p>For a database dependency, the <code>service_healthy<\/code> condition under <code>depends_on<\/code> for service <code>db<\/code> belongs in the application service, with a real healthcheck on the database service. This gates startup managed by Compose. It is not continuous dependency supervision and is not rerun as a Compose readiness gate when Docker independently restarts containers after a host reboot. Applications still need bounded retries and reconnection logic.<\/p>\n<h2>Bounded logs and resource use<\/h2>\n<p>Docker\u2019s default json-file driver has no rotation unless configured. The example keeps up to three rotated log files of approximately 10 MB each per container. Replicas multiply that budget; application files, volumes and other host logs are outside it. Neither 30 MB nor a retention duration is universally sufficient. Docker also recommends the local driver for many installations because rotation is enabled by default.<\/p>\n<p>Daemon-wide defaults belong in the existing daemon configuration, merged with other settings. After the daemon applies the new defaults, existing containers retain their old logging configuration until recreated. The journald driver is another option, but it does not itself make logs memory-only: <code>Storage=volatile<\/code> stores new journal data under <code>\/run\/log\/journal<\/code>, which is lost on reboot. Existing persistent journal files are not automatically deleted, and remote retention needs separate configuration.<\/p>\n<p><code>mem_limit<\/code>, <code>cpus<\/code> and <code>pids_limit<\/code> bound different resources. Memory pressure can kill a process inside a container; the whole container only restarts if its main process exits and the restart policy applies. Limits do not guarantee that the host or other services remain unaffected. Aggregate budgets need room for the operating system, Docker, caches and workload peaks. Tmpfs stores temporary files in memory, consumes part of the memory budget and does not preserve files when the container stops.<\/p>\n<p>Raspberry Pi OS does not justify a universal claim that memory control is disabled. Support depends on the kernel, cgroup setup, OS version and operating mode. <code>docker info<\/code>, the effective container configuration and a controlled test on a disposable workload establish actual behavior. Boot parameters need changes only when the installed system\u2019s documentation and diagnostics require them. In <code>cmdline.txt<\/code>, parameters stay on one logical line: a split can hide later parameters, but an ordinary terminating newline does not inevitably make the system unbootable.<\/p>\n<h2>Image identity and privileges<\/h2>\n<p>Restarting an existing container does not pull a new image. Recreating a container may use a newer local or downloaded image, depending on the pull policy and cache. A tag can move; a digest identifies fixed image content. Pinning therefore needs a deliberate update process, including reviewed digest changes, platform compatibility and rollback planning. A fixed image does not freeze volume contents, external services or database schema.<\/p>\n<p><code>docker buildx imagetools inspect IMAGE:TAG<\/code> shows registry metadata. A multi-platform index digest references several platform manifests; a platform-specific manifest digest fixes one variant. Both can be valid for a deliberate deployment. A local RepoDigests entry is not a universal guarantee of an index digest, and locally built images may have no repository digest. The selected Pi architecture must actually exist in the index. Mismatches can fail during selection, creation or execution depending on platform settings and emulation.<\/p>\n<p><code>user: \"1000:1000\"<\/code> selects an identity; compatibility depends on image startup behavior and volume permissions. <code>no-new-privileges<\/code> blocks acquiring additional privileges through mechanisms such as setuid executables, but does not remove privileges already granted or turn root into a non-root user. Read-only root filesystems leave explicitly writable mounts writable. These controls require application tests, not a promise that every application will keep working unchanged.<\/p>\n<h2>Configuration checks with an explicit policy<\/h2>\n<p><code>docker compose config -q<\/code> validates and resolves the Compose model without printing it. Unset ordinary variables normally cause a warning and an empty substitution; <code>${VAR:?message}<\/code> instead rejects unset or empty required values. Resolved output can contain secrets and needs protected storage.<\/p>\n<p>The following checker is saved as <code>check-compose.py<\/code>. It enforces the narrow example policy: every listed service is long-running, explicitly declares an active healthcheck and the shown JSON rotation, and has a SHA-256 image reference. Inherited image healthchecks, host logging defaults and other valid policies are deliberately not inferred.<\/p>\n<figure style=\"--cbb-digits:2\" class=\"cbb cbb--wrap cbb--numbers wp-block-code-beautifier-block-code\" data-lang=\"python\"><figcaption class=\"cbb-head\"><span class=\"cbb-lang\">Python<\/span><span class=\"cbb-actions\"><button type=\"button\" class=\"cbb-button cbb-button--wrap\" data-cbb-action=\"wrap\" aria-pressed=\"true\" title=\"Wrap long lines\"><svg aria-hidden=\"true\" focusable=\"false\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"><path d=\"M2 4h12M2 8h9.5a2.5 2.5 0 0 1 0 5H8m0 0 1.5-1.5M8 13l1.5 1.5M2 12h3\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/><\/svg><span class=\"cbb-sr\">Wrap long lines<\/span><\/button><button type=\"button\" class=\"cbb-button cbb-button--copy\" data-cbb-action=\"copy\" data-cbb-done=\"Copied\" data-cbb-failed=\"Press Ctrl+C to copy\"><svg aria-hidden=\"true\" focusable=\"false\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"><rect x=\"5.5\" y=\"5.5\" width=\"8\" height=\"8.5\" rx=\"1.5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"\/><path d=\"M10.5 3.5V3A1.5 1.5 0 0 0 9 1.5H4A1.5 1.5 0 0 0 2.5 3v6.5A1.5 1.5 0 0 0 4 11h.5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"\/><\/svg><span class=\"cbb-button-label\" aria-live=\"polite\">Copy<\/span><\/button><\/span><\/figcaption><pre class=\"cbb-pre\" tabindex=\"0\"><code class=\"cbb-code language-python\" style=\"counter-reset:cbb-line 0;\"><span class=\"cbb-line\"><span class=\"cbb-keyword\">import<\/span> json\n<\/span><span class=\"cbb-line\"><span class=\"cbb-keyword\">import<\/span> re\n<\/span><span class=\"cbb-line\"><span class=\"cbb-keyword\">import<\/span> sys\n<\/span><span class=\"cbb-line\">\n<\/span><span class=\"cbb-line\">stack = json.<span class=\"cbb-function\">load<\/span>(sys.stdin)\n<\/span><span class=\"cbb-line\">failed = <span class=\"cbb-constant\">False<\/span>\n<\/span><span class=\"cbb-line\"><span class=\"cbb-keyword\">for<\/span> name, svc <span class=\"cbb-keyword\">in<\/span> stack.<span class=\"cbb-function\">get<\/span>(<span class=\"cbb-string\">\"services\"<\/span>, {}).<span class=\"cbb-function\">items<\/span>():\n<\/span><span class=\"cbb-line\">    issues = &#91;&#93;\n<\/span><span class=\"cbb-line\">    <span class=\"cbb-keyword\">if<\/span> svc.<span class=\"cbb-function\">get<\/span>(<span class=\"cbb-string\">\"restart\"<\/span>) <span class=\"cbb-keyword\">not<\/span> <span class=\"cbb-keyword\">in<\/span> (<span class=\"cbb-string\">\"always\"<\/span>, <span class=\"cbb-string\">\"unless-stopped\"<\/span>):\n<\/span><span class=\"cbb-line\">        issues.<span class=\"cbb-function\">append<\/span>(<span class=\"cbb-string\">\"restart policy needs review\"<\/span>)\n<\/span><span class=\"cbb-line\">    health = svc.<span class=\"cbb-function\">get<\/span>(<span class=\"cbb-string\">\"healthcheck\"<\/span>) <span class=\"cbb-keyword\">or<\/span> {}\n<\/span><span class=\"cbb-line\">    test = health.<span class=\"cbb-function\">get<\/span>(<span class=\"cbb-string\">\"test\"<\/span>) <span class=\"cbb-keyword\">or<\/span> &#91;&#93;\n<\/span><span class=\"cbb-line\">    <span class=\"cbb-keyword\">if<\/span> health.<span class=\"cbb-function\">get<\/span>(<span class=\"cbb-string\">\"disable\"<\/span>) <span class=\"cbb-keyword\">or<\/span> <span class=\"cbb-keyword\">not<\/span> test <span class=\"cbb-keyword\">or<\/span> test&#91;<span class=\"cbb-number\">0<\/span>&#93; == <span class=\"cbb-string\">\"NONE\"<\/span>:\n<\/span><span class=\"cbb-line\">        issues.<span class=\"cbb-function\">append<\/span>(<span class=\"cbb-string\">\"explicit active healthcheck missing\"<\/span>)\n<\/span><span class=\"cbb-line\">    log = svc.<span class=\"cbb-function\">get<\/span>(<span class=\"cbb-string\">\"logging\"<\/span>) <span class=\"cbb-keyword\">or<\/span> {}\n<\/span><span class=\"cbb-line\">    opts = log.<span class=\"cbb-function\">get<\/span>(<span class=\"cbb-string\">\"options\"<\/span>) <span class=\"cbb-keyword\">or<\/span> {}\n<\/span><span class=\"cbb-line\">    <span class=\"cbb-keyword\">if<\/span> log.<span class=\"cbb-function\">get<\/span>(<span class=\"cbb-string\">\"driver\"<\/span>) != <span class=\"cbb-string\">\"json-file\"<\/span>:\n<\/span><span class=\"cbb-line\">        issues.<span class=\"cbb-function\">append<\/span>(<span class=\"cbb-string\">\"logging differs from this example policy\"<\/span>)\n<\/span><span class=\"cbb-line\">    <span class=\"cbb-keyword\">elif<\/span> opts.<span class=\"cbb-function\">get<\/span>(<span class=\"cbb-string\">\"max-size\"<\/span>) != <span class=\"cbb-string\">\"10m\"<\/span> <span class=\"cbb-keyword\">or<\/span> <span class=\"cbb-function\">str<\/span>(opts.<span class=\"cbb-function\">get<\/span>(<span class=\"cbb-string\">\"max-file\"<\/span>)) != <span class=\"cbb-string\">\"3\"<\/span>:\n<\/span><span class=\"cbb-line\">        issues.<span class=\"cbb-function\">append<\/span>(<span class=\"cbb-string\">\"example log rotation limits missing\"<\/span>)\n<\/span><span class=\"cbb-line\">    <span class=\"cbb-keyword\">if<\/span> <span class=\"cbb-keyword\">not<\/span> re.<span class=\"cbb-function\">search<\/span>(<span class=\"cbb-string\">r\"@sha256:&#91;0-9a-f&#93;{64}$\"<\/span>, svc.<span class=\"cbb-function\">get<\/span>(<span class=\"cbb-string\">\"image\"<\/span>, <span class=\"cbb-string\">\"\"<\/span>)):\n<\/span><span class=\"cbb-line\">        issues.<span class=\"cbb-function\">append<\/span>(<span class=\"cbb-string\">\"SHA-256 image reference missing\"<\/span>)\n<\/span><span class=\"cbb-line\">    result = <span class=\"cbb-string\">\"; \"<\/span>.<span class=\"cbb-function\">join<\/span>(issues) <span class=\"cbb-keyword\">if<\/span> issues <span class=\"cbb-keyword\">else<\/span> <span class=\"cbb-string\">\"example policy matched\"<\/span>\n<\/span><span class=\"cbb-line\">    <span class=\"cbb-function\">print<\/span>(<span class=\"cbb-string\">\"{}: {}\"<\/span>.<span class=\"cbb-function\">format<\/span>(name, result))\n<\/span><span class=\"cbb-line\">    failed = failed <span class=\"cbb-keyword\">or<\/span> <span class=\"cbb-function\">bool<\/span>(issues)\n<\/span><span class=\"cbb-line\"><span class=\"cbb-keyword\">if<\/span> <span class=\"cbb-keyword\">not<\/span> stack.<span class=\"cbb-function\">get<\/span>(<span class=\"cbb-string\">\"services\"<\/span>):\n<\/span><span class=\"cbb-line\">    <span class=\"cbb-function\">print<\/span>(<span class=\"cbb-string\">\"no services found\"<\/span>, file=sys.stderr)\n<\/span><span class=\"cbb-line\">    sys.<span class=\"cbb-function\">exit<\/span>(<span class=\"cbb-number\">2<\/span>)\n<\/span><span class=\"cbb-line\">sys.<span class=\"cbb-function\">exit<\/span>(<span class=\"cbb-number\">1<\/span> <span class=\"cbb-keyword\">if<\/span> failed <span class=\"cbb-keyword\">else<\/span> <span class=\"cbb-number\">0<\/span>)<\/span><\/code><\/pre><\/figure>\n<pre><code>umask 077\ndocker compose config --format json &gt; resolved.json &amp;&amp; python3 check-compose.py &lt; resolved.json<\/code><\/pre>\n<p>A zero exit status means only that this policy matched the resolved model. It does not verify the digest in a registry, probe the application, prove resource enforcement or certify security. The checker reports issues with exit status 1; empty service input returns 2. The preceding Compose command must succeed before checking its output.<\/p>\n<h2>Recovery tests and useful signals<\/h2>\n<p>A controlled maintenance test covers application exit, dependency outage, host reboot, intentionally stopped services and restoration from a backup. Merely restarting a container does not test data recovery. Container state, increasing restart count, health output, disk space, memory pressure and an external availability probe provide complementary evidence. An alert should identify a sustained problem rather than notify on every harmless state change.<\/p>\n<h3>Does unhealthy mean that Docker will repair the service?<\/h3><p>No. Health status is diagnostic information in this Compose setup. A failed probe and its cause require inspection; automatic recovery needs an explicit strategy.<\/p>\n<h3>Are pinned images incompatible with automatic updates?<\/h3><p>No. An updater can propose or apply a reviewed digest change. Repeatedly pulling the same digest alone does not select a new version, and updater success behavior depends on the tool.<\/p>\n<h3>Why can hardening prevent startup?<\/h3><p>An entrypoint may need writable paths or an initial permission adjustment. The image\u2019s documented runtime user and required mounts determine the solution. Arbitrarily changing host ownership is not a universal fix.<\/p>\n<h2>Sources<\/h2><ul><li><a href=\"https:\/\/docs.docker.com\/engine\/containers\/start-containers-automatically\/\">Docker: Start containers automatically<\/a><\/li><li><a href=\"https:\/\/docs.docker.com\/engine\/containers\/resource_constraints\/\">Docker: Resource constraints<\/a><\/li><li><a href=\"https:\/\/docs.docker.com\/compose\/how-tos\/startup-order\/\">Docker Compose: Control startup and shutdown order<\/a><\/li><li><a href=\"https:\/\/docs.docker.com\/reference\/compose-file\/interpolation\/\">Docker Compose: Interpolation<\/a><\/li><li><a href=\"https:\/\/docs.docker.com\/engine\/logging\/drivers\/json-file\/\">Docker: JSON File logging driver<\/a><\/li><li><a href=\"https:\/\/docs.docker.com\/engine\/logging\/configure\/\">Docker: Configure logging drivers<\/a><\/li><li><a href=\"https:\/\/docs.docker.com\/reference\/dockerfile\/\">Dockerfile reference: HEALTHCHECK<\/a><\/li><li><a href=\"https:\/\/docs.docker.com\/reference\/cli\/docker\/buildx\/imagetools\/inspect\/\">Docker Buildx: imagetools inspect<\/a><\/li><li><a href=\"https:\/\/docs.docker.com\/reference\/compose-file\/services\/\">Docker Compose: Services reference<\/a><\/li><li><a href=\"https:\/\/docs.docker.com\/reference\/cli\/docker\/compose\/config\/\">Docker Compose: config command<\/a><\/li><li><a href=\"https:\/\/www.freedesktop.org\/software\/systemd\/man\/latest\/journald.conf.html\">systemd: journald.conf and Storage<\/a><\/li><li><a href=\"https:\/\/www.raspberrypi.com\/documentation\/computers\/configuration.html\">Raspberry Pi: Kernel command line configuration<\/a><\/li><li><a href=\"https:\/\/docs.docker.com\/reference\/cli\/docker\/container\/run\/\">Docker: container run security options<\/a><\/li><\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Restart policies, health checks, log rotation and resource limits address different operating risks. A validated Compose example and a focused policy checker show the controls and their limits; monitoring, updates and tested recovery remain necessary.<\/p>\n","protected":false},"author":1,"featured_media":24238,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[92630],"tags":[91144,91145,91181,91237,91219],"class_list":["post-13041","post","type-post","status-publish","format-standard","hentry","category-tutorials-en-raspberry-pi","tag-devops","tag-docker","tag-raspberry-pi","tag-self-hosting","tag-tutorial"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Tutorial: Hardening a Docker Compose File for Unattended Operation on a Raspberry Pi | Lukas Wojcik<\/title>\n<meta name=\"description\" content=\"Restart policy, healthcheck, log rotation, memory limit and a pinned digest: the six lines that keep a Compose stack running unattended on a Raspberry Pi.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.lukaswojcik.com\/blog\/en\/raspberry-pi\/tutorials-en-raspberry-pi\/tutorial-hardening-a-docker-compose-file-for-unattended-operation-on-a-raspberry-pi\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Tutorial: Hardening a Docker Compose File for Unattended Operation on a Raspberry Pi | Lukas Wojcik\" \/>\n<meta property=\"og:description\" content=\"Restart policy, healthcheck, log rotation, memory limit and a pinned digest: the six lines that keep a Compose stack running unattended on a Raspberry Pi.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.lukaswojcik.com\/blog\/en\/raspberry-pi\/tutorials-en-raspberry-pi\/tutorial-hardening-a-docker-compose-file-for-unattended-operation-on-a-raspberry-pi\/\" \/>\n<meta property=\"og:site_name\" content=\"Lukas Wojcik - Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-09-16T05:35:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-10-26T11:07:07+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/10\/hero-13041-composehard-20261024-dark.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Lukas Wojcik\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Lukas Wojcik\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/raspberry-pi\\\/tutorials-en-raspberry-pi\\\/tutorial-hardening-a-docker-compose-file-for-unattended-operation-on-a-raspberry-pi\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/raspberry-pi\\\/tutorials-en-raspberry-pi\\\/tutorial-hardening-a-docker-compose-file-for-unattended-operation-on-a-raspberry-pi\\\/\"},\"author\":{\"name\":\"Lukas Wojcik\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\"},\"headline\":\"Tutorial: Hardening a Docker Compose File for Unattended Operation on a Raspberry Pi\",\"datePublished\":\"2026-09-16T05:35:00+00:00\",\"dateModified\":\"2026-10-26T11:07:07+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/raspberry-pi\\\/tutorials-en-raspberry-pi\\\/tutorial-hardening-a-docker-compose-file-for-unattended-operation-on-a-raspberry-pi\\\/\"},\"wordCount\":1359,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\"},\"image\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/raspberry-pi\\\/tutorials-en-raspberry-pi\\\/tutorial-hardening-a-docker-compose-file-for-unattended-operation-on-a-raspberry-pi\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/hero-13041-composehard-20261024-dark.png\",\"keywords\":[\"DevOps\",\"Docker\",\"Raspberry Pi\",\"Self-Hosting\",\"Tutorial\"],\"articleSection\":[\"Tutorials\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/raspberry-pi\\\/tutorials-en-raspberry-pi\\\/tutorial-hardening-a-docker-compose-file-for-unattended-operation-on-a-raspberry-pi\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/raspberry-pi\\\/tutorials-en-raspberry-pi\\\/tutorial-hardening-a-docker-compose-file-for-unattended-operation-on-a-raspberry-pi\\\/\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/raspberry-pi\\\/tutorials-en-raspberry-pi\\\/tutorial-hardening-a-docker-compose-file-for-unattended-operation-on-a-raspberry-pi\\\/\",\"name\":\"Tutorial: Hardening a Docker Compose File for Unattended Operation on a Raspberry Pi | Lukas Wojcik\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/raspberry-pi\\\/tutorials-en-raspberry-pi\\\/tutorial-hardening-a-docker-compose-file-for-unattended-operation-on-a-raspberry-pi\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/raspberry-pi\\\/tutorials-en-raspberry-pi\\\/tutorial-hardening-a-docker-compose-file-for-unattended-operation-on-a-raspberry-pi\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/hero-13041-composehard-20261024-dark.png\",\"datePublished\":\"2026-09-16T05:35:00+00:00\",\"dateModified\":\"2026-10-26T11:07:07+00:00\",\"description\":\"Restart policy, healthcheck, log rotation, memory limit and a pinned digest: the six lines that keep a Compose stack running unattended on a Raspberry Pi.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/raspberry-pi\\\/tutorials-en-raspberry-pi\\\/tutorial-hardening-a-docker-compose-file-for-unattended-operation-on-a-raspberry-pi\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/raspberry-pi\\\/tutorials-en-raspberry-pi\\\/tutorial-hardening-a-docker-compose-file-for-unattended-operation-on-a-raspberry-pi\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/raspberry-pi\\\/tutorials-en-raspberry-pi\\\/tutorial-hardening-a-docker-compose-file-for-unattended-operation-on-a-raspberry-pi\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/hero-13041-composehard-20261024-dark.png\",\"contentUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/hero-13041-composehard-20261024-dark.png\",\"width\":1200,\"height\":630,\"caption\":\"Tutorial: Hardening a Docker Compose File for Unattended Operation on a Raspberry Pi\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/raspberry-pi\\\/tutorials-en-raspberry-pi\\\/tutorial-hardening-a-docker-compose-file-for-unattended-operation-on-a-raspberry-pi\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Tutorial: Hardening a Docker Compose File for Unattended Operation on a Raspberry Pi\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\",\"name\":\"Lukas Wojcik - Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\",\"name\":\"Lukas Wojcik\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"contentUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"width\":424,\"height\":636,\"caption\":\"Lukas Wojcik\"},\"logo\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\"},\"sameAs\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Tutorial: Hardening a Docker Compose File for Unattended Operation on a Raspberry Pi | Lukas Wojcik","description":"Restart policy, healthcheck, log rotation, memory limit and a pinned digest: the six lines that keep a Compose stack running unattended on a Raspberry Pi.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.lukaswojcik.com\/blog\/en\/raspberry-pi\/tutorials-en-raspberry-pi\/tutorial-hardening-a-docker-compose-file-for-unattended-operation-on-a-raspberry-pi\/","og_locale":"en_US","og_type":"article","og_title":"Tutorial: Hardening a Docker Compose File for Unattended Operation on a Raspberry Pi | Lukas Wojcik","og_description":"Restart policy, healthcheck, log rotation, memory limit and a pinned digest: the six lines that keep a Compose stack running unattended on a Raspberry Pi.","og_url":"https:\/\/www.lukaswojcik.com\/blog\/en\/raspberry-pi\/tutorials-en-raspberry-pi\/tutorial-hardening-a-docker-compose-file-for-unattended-operation-on-a-raspberry-pi\/","og_site_name":"Lukas Wojcik - Blog","article_published_time":"2026-09-16T05:35:00+00:00","article_modified_time":"2026-10-26T11:07:07+00:00","og_image":[{"width":1200,"height":630,"url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/10\/hero-13041-composehard-20261024-dark.png","type":"image\/png"}],"author":"Lukas Wojcik","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Lukas Wojcik","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/raspberry-pi\/tutorials-en-raspberry-pi\/tutorial-hardening-a-docker-compose-file-for-unattended-operation-on-a-raspberry-pi\/#article","isPartOf":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/raspberry-pi\/tutorials-en-raspberry-pi\/tutorial-hardening-a-docker-compose-file-for-unattended-operation-on-a-raspberry-pi\/"},"author":{"name":"Lukas Wojcik","@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9"},"headline":"Tutorial: Hardening a Docker Compose File for Unattended Operation on a Raspberry Pi","datePublished":"2026-09-16T05:35:00+00:00","dateModified":"2026-10-26T11:07:07+00:00","mainEntityOfPage":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/raspberry-pi\/tutorials-en-raspberry-pi\/tutorial-hardening-a-docker-compose-file-for-unattended-operation-on-a-raspberry-pi\/"},"wordCount":1359,"commentCount":0,"publisher":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9"},"image":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/raspberry-pi\/tutorials-en-raspberry-pi\/tutorial-hardening-a-docker-compose-file-for-unattended-operation-on-a-raspberry-pi\/#primaryimage"},"thumbnailUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/10\/hero-13041-composehard-20261024-dark.png","keywords":["DevOps","Docker","Raspberry Pi","Self-Hosting","Tutorial"],"articleSection":["Tutorials"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.lukaswojcik.com\/blog\/en\/raspberry-pi\/tutorials-en-raspberry-pi\/tutorial-hardening-a-docker-compose-file-for-unattended-operation-on-a-raspberry-pi\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/raspberry-pi\/tutorials-en-raspberry-pi\/tutorial-hardening-a-docker-compose-file-for-unattended-operation-on-a-raspberry-pi\/","url":"https:\/\/www.lukaswojcik.com\/blog\/en\/raspberry-pi\/tutorials-en-raspberry-pi\/tutorial-hardening-a-docker-compose-file-for-unattended-operation-on-a-raspberry-pi\/","name":"Tutorial: Hardening a Docker Compose File for Unattended Operation on a Raspberry Pi | Lukas Wojcik","isPartOf":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/raspberry-pi\/tutorials-en-raspberry-pi\/tutorial-hardening-a-docker-compose-file-for-unattended-operation-on-a-raspberry-pi\/#primaryimage"},"image":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/raspberry-pi\/tutorials-en-raspberry-pi\/tutorial-hardening-a-docker-compose-file-for-unattended-operation-on-a-raspberry-pi\/#primaryimage"},"thumbnailUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/10\/hero-13041-composehard-20261024-dark.png","datePublished":"2026-09-16T05:35:00+00:00","dateModified":"2026-10-26T11:07:07+00:00","description":"Restart policy, healthcheck, log rotation, memory limit and a pinned digest: the six lines that keep a Compose stack running unattended on a Raspberry Pi.","breadcrumb":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/raspberry-pi\/tutorials-en-raspberry-pi\/tutorial-hardening-a-docker-compose-file-for-unattended-operation-on-a-raspberry-pi\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.lukaswojcik.com\/blog\/en\/raspberry-pi\/tutorials-en-raspberry-pi\/tutorial-hardening-a-docker-compose-file-for-unattended-operation-on-a-raspberry-pi\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/raspberry-pi\/tutorials-en-raspberry-pi\/tutorial-hardening-a-docker-compose-file-for-unattended-operation-on-a-raspberry-pi\/#primaryimage","url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/10\/hero-13041-composehard-20261024-dark.png","contentUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/10\/hero-13041-composehard-20261024-dark.png","width":1200,"height":630,"caption":"Tutorial: Hardening a Docker Compose File for Unattended Operation on a Raspberry Pi"},{"@type":"BreadcrumbList","@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/raspberry-pi\/tutorials-en-raspberry-pi\/tutorial-hardening-a-docker-compose-file-for-unattended-operation-on-a-raspberry-pi\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.lukaswojcik.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Tutorial: Hardening a Docker Compose File for Unattended Operation on a Raspberry Pi"}]},{"@type":"WebSite","@id":"https:\/\/www.lukaswojcik.com\/blog\/#website","url":"https:\/\/www.lukaswojcik.com\/blog\/","name":"Lukas Wojcik - Blog","description":"","publisher":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.lukaswojcik.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9","name":"Lukas Wojcik","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","contentUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","width":424,"height":636,"caption":"Lukas Wojcik"},"logo":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg"},"sameAs":["https:\/\/www.lukaswojcik.com\/blog"]}]}},"_links":{"self":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/posts\/13041","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/comments?post=13041"}],"version-history":[{"count":5,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/posts\/13041\/revisions"}],"predecessor-version":[{"id":26775,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/posts\/13041\/revisions\/26775"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/media\/24238"}],"wp:attachment":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/media?parent=13041"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/categories?post=13041"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/tags?post=13041"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}