Docker- ja Podman-konttien kovettaminen Linuxissa: Rootless, seccomp, AppArmor ja ajonaikainen valvonta

Käytännön opas Docker- ja Podman-konttien kovettamiseen Linuxissa. Rootless-tila, seccomp-profiilit, AppArmor/SELinux, daemon.json-kovettaminen, Trivy-haavoittuvuusskannaus ja Falco-valvonta esimerkkien kera.

Johdanto: Miksi konttien kovettaminen on välttämätöntä?

Kontit ovat mullistaneet sovellusten käyttöönoton — siitä ei ole epäilystäkään. Docker ja Podman mahdollistavat nopean paketoinnin, skaalauksen ja siirrettävyyden, mutta tässä on se ikävä puoli: nopeus on saanut monet unohtamaan tietoturvan kokonaan. Vuoden 2026 uhkamaisema on sellainen, että hyökkääjät etsivät aktiivisesti väärin konfiguroituja kontteja, haavoittuvia peruskuvia ja paljastettuja Docker-socketeja. Ja se on pelottavaa.

Tutkimusten mukaan jopa virallisissa Docker Hub -kuvissa on keskimäärin yli 70 tunnettua haavoittuvuutta. Luetaan se uudelleen: virallisissa kuvissa.

Tässä oppaassa käydään kerroksittain läpi Linux-konttien kovettaminen: isäntäkoneen suojaus, rootless-tila, ytimen tason rajoitukset (seccomp ja Linux-kyvykkyydet), pakollinen pääsynhallinta (AppArmor/SELinux), konttikuvien skannaus ja ajonaikainen valvonta. Jokainen osio sisältää käytännön komentoja ja konfiguraatioita, joita voit soveltaa suoraan tuotantoympäristöissäsi.

Jos olet jo lukenut aiemman oppaamme SELinux ja AppArmor: Käytännön opas pakolliseen pääsynhallintaan Linuxissa, tämä artikkeli vie tiedon konttimaailmaan — näet käytännössä, miten MAC-profiilit toimivat konttien kanssa.

Docker vs. Podman: Arkkitehtuurierot turvallisuuden näkökulmasta

Dockerin asiakas-palvelin-malli

Docker käyttää asiakas-palvelin-arkkitehtuuria, jossa Docker CLI kommunikoi taustalla pyörivän daemon-prosessin kanssa. Tämä daemon hallinnoi kontteja, kuvia ja verkkoja. Oletuksena se pyörii root-oikeuksilla — mikä tarkoittaa, että kaikki sen käynnistämät kontit perivät suoran yhteyden isäntäkoneen root-tasoon.

Tämä on iso hyökkäyspinta. Jos hyökkääjä pääsee murtautumaan kontista ulos, hänellä on potentiaalisesti root-oikeudet koko isäntäkoneeseen. Tätä kutsutaan Docker socket -oikeuksien eskalaatioksi, ja se on juuri niin paha kuin miltä kuulostaa.

Podmanin daemonaton arkkitehtuuri

Podman tekee asiat toisin. Se käyttää daemonatonta arkkitehtuuria, jossa jokainen komento pyörii omana prosessinaan ilman keskitettyä taustaprosessia. Podman on suunniteltu alusta lähtien rootless-käyttöön — kontit pyörivät oletuksena tavallisen käyttäjän oikeuksilla.

Red Hatin kehitystiimin tutkimuksen mukaan Podman antaa konteille oletuksena vain 11 ytimen kyvykkyyttä, kun Docker antaa 14. Kolme kyvykkyyttä vähemmän kuulostaa ehkä pieneltä erolta, mutta se noudattaa vähimmäisoikeusperiaatetta — ja jokainen pudotettu kyvykkyys on yksi vähemmän mahdollinen hyökkäysvektori.

# Vertaa oletuskyvykkyyksiä
# Docker
docker run --rm alpine cat /proc/1/status | grep Cap

# Podman (rootless)
podman run --rm alpine cat /proc/1/status | grep Cap

Kumpi sitten kannattaa valita?

Jos turvallisuus ja Linux-natiivius ovat ensisijaisia, Podman on rehellisesti sanottuna selkeä valinta. Sen daemonaton, rootless-ensin -arkkitehtuuri vähentää hyökkäyspintaa merkittävästi. Docker on kuitenkin edelleen vahva kehittäjäkokemuksessa ja laajassa ekosysteemituessa — ja käytännössä molemmissa on mahdollista saavuttaa korkea turvallisuustaso. Kyse on lopulta konfiguraatiosta.

Rootless-konttien käyttöönotto

Podman: Rootless oletuksena

Podmanissa rootless-tila toimii suoraan paketista. Erityiskonfiguraatiota ei tarvita. Jokainen käyttäjä saa omat UID-alueet, erilliset kontti- ja kuvavarastot, eikä voi vaikuttaa toisten käyttäjien kontteihin.

# Tarkista, että Podman pyörii rootless-tilassa
podman info --format '{{.Host.Security.Rootless}}'
true

# Tarkista UID-mappaus
podman unshare cat /proc/self/uid_map
         0       1000          1
         1     100000      65536

# Käynnistä kontti rootless-tilassa (oletus)
podman run -d --name web-palvelin -p 8080:80 nginx:alpine

Kontin sisällä prosessi näkee olevansa root (UID 0), mutta isäntäkoneella se pyörii tavallisena käyttäjänä. Tässä on se hieno juttu: vaikka hyökkääjä murtautuisi kontista ulos, hänellä olisi vain rajoitetut oikeudet.

Docker: Rootless-tilan käyttöönotto

Dockerissa rootless-tila vaatii erillisen asennuksen. Se on ollut saatavilla Docker 19.03:sta lähtien, mutta se ei valitettavasti ole oletusasetus.

# Asenna rootless Docker
dockerd-rootless-setuptool.sh install

# Aseta ympäristömuuttujat
export PATH=/usr/bin:$PATH
export DOCKER_HOST=unix:///run/user/$(id -u)/docker.sock

# Tarkista tila
docker info 2>/dev/null | grep -i "rootless\|security"
 Security Options: seccomp, rootless

Docker: Käyttäjänimiavaruuden uudelleenmappaus (userns-remap)

Jos rootless-tila ei jostain syystä ole mahdollinen (esimerkiksi yhteensopivuussyistä), userns-remap on vahva vaihtoehto. Se mappaa kontin root-käyttäjän isäntäkoneen ei-etuoikeutettuun UID:iin.

# Konfiguroi /etc/docker/daemon.json
{
  "userns-remap": "default"
}

# Käynnistä Docker-daemon uudelleen
sudo systemctl restart docker

# Tarkista mappaus
# Kontin UID 0 = Isäntäkoneen UID 100000
cat /etc/subuid
dockremap:100000:65536

Huomio: userns-remap ei ole yhteensopiva --pid=host-, --network=host- tai --privileged-valintojen kanssa ilman --userns=host-lisämääritystä. Tämä on yksi niistä pienistä kompromisseista, jotka kannattaa tiedostaa etukäteen.

Docker-daemonin kovettaminen: daemon.json

Docker-daemonin konfiguraatiotiedosto /etc/docker/daemon.json on ensimmäinen puolustuslinja. Alla on vuoden 2026 turvallisuusvaatimukset täyttävä peruskonfiguraatio, jota olen itse käyttänyt lähtökohtana useissa projekteissa:

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  },
  "storage-driver": "overlay2",
  "exec-opts": ["native.cgroupdriver=systemd"],
  "live-restore": true,
  "userns-remap": "default",
  "no-new-privileges": true,
  "icc": false,
  "userland-proxy": false,
  "default-ulimits": {
    "nofile": {
      "Name": "nofile",
      "Hard": 64000,
      "Soft": 64000
    }
  }
}

Käydään läpi tärkeimmät asetukset:

  • no-new-privileges: true — Estää oikeuksien eskalaation setuid-binäärien kautta kontin sisällä. Tämä on yksi tärkeimmistä yksittäisistä asetuksista, ja suosittelen sen käyttöönottoa aina.
  • userns-remap: "default" — Mappaa kontin root-käyttäjän ei-etuoikeutettuun UID:iin isäntäkoneella.
  • icc: false — Estää konttien välisen vapaan verkkoliikenteen. Kontit voivat kommunikoida vain erikseen linkitettyjen verkkojen kautta. Tämä on yllättävän usein unohdettu asetus.
  • live-restore: true — Kontit jatkavat pyörimistä, vaikka daemon käynnistetään uudelleen päivitysten yhteydessä. Käytännöllinen tuotannossa.
  • userland-proxy: false — Käyttää iptables/nftables-sääntöjä userland-proxyn sijaan, mikä vähentää hyökkäyspintaa.
  • Lokirotaatio — Estää lokien täyttämästä levytilaa (10 Mt × 3 tiedostoa per kontti). Pieni yksityiskohta, mutta säästää monelta päänsäryltä.
# Vahvista konfiguraatio ja käynnistä uudelleen
sudo dockerd --validate
sudo systemctl restart docker

# Tarkista asetukset
docker info | grep -E "Remap|Privilege|ICC"

Seccomp: Järjestelmäkutsujen rajoittaminen

Mitä seccomp oikeastaan tekee?

Seccomp (Secure Computing Mode) on Linux-ytimen ominaisuus, joka rajoittaa kontin käytettävissä olevia järjestelmäkutsuja. Ajattele sitä niin, että kerrot ytimelle: "tämä prosessi saa tehdä vain nämä asiat, ei mitään muuta." Dockerin oletusprofiili estää noin 44 järjestelmäkutsua yli 300:sta, mutta tuotantoympäristössä kannattaa ehdottomasti luoda sovelluskohtaiset profiilit.

Oletusprofiilin tarkistaminen

# Tarkista, onko seccomp käytössä
docker info --format '{{ .SecurityOptions }}'
[name=seccomp,profile=builtin]

# Aja kontti oletusprofiililla (automaattinen)
docker run --rm -it alpine sh

# Testaa estettyä järjestelmäkutsua
# unshare on oletuksena estetty
docker run --rm -it alpine unshare --map-root-user whoami
# unshare: Operation not permitted

Mukautetun seccomp-profiilin luominen

Paras käytäntö on luoda sovelluskohtainen profiili, joka sallii vain ne järjestelmäkutsut, joita sovellus oikeasti tarvitsee. Tässä esimerkki Nginx-palvelimelle:

{
  "defaultAction": "SCMP_ACT_ERRNO",
  "architectures": ["SCMP_ARCH_X86_64"],
  "syscalls": [
    {
      "names": [
        "accept4", "bind", "clone", "close", "connect",
        "epoll_create1", "epoll_ctl", "epoll_wait",
        "eventfd2", "fstat", "futex", "getdents64",
        "getpid", "getuid", "ioctl", "listen",
        "mmap", "mprotect", "munmap", "nanosleep",
        "open", "openat", "read", "recvfrom",
        "rt_sigaction", "rt_sigprocmask", "sendto",
        "set_robust_list", "setsockopt", "socket",
        "write", "writev"
      ],
      "action": "SCMP_ACT_ALLOW"
    }
  ]
}
# Käytä mukautettua profiilia
docker run -d --name nginx-kovennettu \
  --security-opt seccomp=/etc/docker/seccomp/nginx-profile.json \
  -p 8080:80 \
  nginx:alpine

# Podmanissa vastaavasti
podman run -d --name nginx-kovennettu \
  --security-opt seccomp=/etc/containers/seccomp/nginx-profile.json \
  -p 8080:80 \
  nginx:alpine

Varoitus: --privileged-lipun käyttö poistaa seccompin käytöstä kokonaan. Älä koskaan käytä --privileged-lippua tuotantoympäristössä, ellei siihen ole aivan ehdoton pakko — ja silloinkin mieti kaksi kertaa.

Linux-kyvykkyyksien pudottaminen

Linux-kyvykkyydet (capabilities) jakavat root-oikeudet pienempiin, hallittaviin osiin. Idea on yksinkertainen: sen sijaan, että kontti saisi kaikki root-oikeudet, annetaan sille vain ne, joita se oikeasti tarvitsee. Oletuskyvykkyydet ovat usein liian sallivia.

# Pudota KAIKKI kyvykkyydet ja lisää vain tarvittavat
docker run -d --name turvallinen-web \
  --cap-drop ALL \
  --cap-add NET_BIND_SERVICE \
  --cap-add CHOWN \
  --cap-add SETUID \
  --cap-add SETGID \
  nginx:alpine

# Tarkista kontin kyvykkyydet
docker exec turvallinen-web cat /proc/1/status | grep Cap
CapPrm: 0000000000001c21
CapEff: 0000000000001c21

# Podmanissa
podman run -d --name turvallinen-web \
  --cap-drop ALL \
  --cap-add NET_BIND_SERVICE \
  nginx:alpine

Erityisen vaarallisia kyvykkyyksiä, jotka tulisi aina pudottaa:

  • CAP_SYS_ADMIN — Käytännössä antaa täydet root-oikeudet isäntäkoneeseen. Tämä on se kyvykkyys, josta painajaiset on tehty.
  • CAP_NET_RAW — Mahdollistaa raakaverkkopakettien lähettämisen (ARP-spoofing yms.)
  • CAP_SYS_PTRACE — Mahdollistaa muiden prosessien debuggauksen
  • CAP_DAC_OVERRIDE — Ohittaa tiedostojärjestelmän käyttöoikeustarkistukset

AppArmor ja SELinux konttien kanssa

AppArmor-profiilit Docker-konteille

Docker luo ja lataa automaattisesti docker-default-nimisen AppArmor-profiilin kaikille konteille. Se on ihan kelvollinen lähtökohta, mutta tuotantoympäristöissä kannattaa ehdottomasti luoda sovelluskohtaiset profiilit. Tässä esimerkki Nginx-profiilista:

# /etc/apparmor.d/containers/docker-nginx
#include <tunables/global>

profile docker-nginx flags=(attach_disconnected,mediate_deleted) {
  #include <abstractions/base>
  #include <abstractions/nameservice>

  # Salli verkkotoiminnot
  network inet tcp,
  network inet6 tcp,

  # Salli Nginx-tiedostot
  /usr/sbin/nginx mr,
  /etc/nginx/** r,
  /var/log/nginx/** rw,
  /var/cache/nginx/** rw,
  /run/nginx.pid rw,

  # Salli web-sisältö (vain luku)
  /usr/share/nginx/html/** r,

  # Estä kaikki muu tiedostopääsy
  deny /etc/shadow r,
  deny /etc/passwd w,
  deny /proc/*/mem rw,
}
# Lataa profiili
sudo apparmor_parser -r -W /etc/apparmor.d/containers/docker-nginx

# Käynnistä kontti mukautetulla profiililla
docker run -d --name nginx-apparmor \
  --security-opt apparmor=docker-nginx \
  -p 8080:80 \
  nginx:alpine

# Tarkista profiilin tila
sudo aa-status | grep docker-nginx

SELinux ja konttien eristäminen (MCS)

SELinux käyttää Multi-Category Security (MCS) -mekanismia konttien eristämiseen. Käytännössä jokaiselle kontille annetaan automaattisesti uniikki kategoriapari, jolloin kontit eivät yksinkertaisesti pysty lukemaan toistensa tiedostoja — vaikka ne pyörisivät samalla isäntäkoneella.

# Tarkista kontin SELinux-konteksti (RHEL/Fedora)
podman run --rm -it fedora cat /proc/1/attr/current
system_u:system_r:container_t:s0:c123,c456

# Toinen kontti saa eri kategoriat
podman run --rm -it fedora cat /proc/1/attr/current
system_u:system_r:container_t:s0:c789,c012

# Nämä kontit eivät pysty lukemaan toistensa tiedostoja,
# vaikka ne pyörisivät samalla isäntäkoneella

# Pakota tietty SELinux-konteksti
podman run -d --name eristetty \
  --security-opt label=level:s0:c100,c200 \
  fedora sleep infinity

Jos olet perehtynyt SELinuxin perusteisiin aiemman SELinux ja AppArmor -oppaamme kautta, tämä MCS-mekanismi on juuri sama, jota Red Hat OpenShift käyttää konttien väliseen eristämiseen tuotannossa. Eli teoriasta käytäntöön matka on lyhyt.

Konttikuvien turvallisuus ja skannaus Trivyllä

Turvalliset peruskuvat

Konttikuvan valinta on ensimmäinen turvallisuuspäätös, jonka teet — ja sillä on yllättävän suuri vaikutus. Yleiset säännöt:

  • Käytä distroless- tai Alpine-kuvia — Pienempi hyökkäyspinta, vähemmän haavoittuvuuksia
  • Käytä multi-stage-rakennuksia — Rakennustyökalut eivät päädy tuotantokuvaan
  • Kiinnitä versiot digestillä — Estää odottamattomat muutokset peruskuvissa
  • Älä koskaan tallenna salaisuuksia kuvakerroksiin — Käytä Docker secrets- tai Vault-mekanismeja (tämä kuulostaa itsestäänselvyydeltä, mutta näkee yllättävän usein)
# Esimerkki turvallisesta multi-stage Dockerfilestä
FROM golang:1.23-alpine AS build
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o /app/server

FROM gcr.io/distroless/static-debian12:nonroot
COPY --from=build /app/server /server
USER nonroot:nonroot
ENTRYPOINT ["/server"]

Trivy-skannaus CI/CD-putkessa

Trivy on avoimen lähdekoodin turvallisuusskanneri, joka tunnistaa haavoittuvuudet, väärät konfiguraatiot ja salaisuudet konttikuvista, tiedostojärjestelmistä ja IaC-malleista. Se on noussut nopeasti alan standardiksi — ja hyvästä syystä.

# Asenna Trivy
sudo apt-get install -y trivy  # Debian/Ubuntu
# tai
sudo dnf install -y trivy      # Fedora/RHEL

# Skannaa konttikuva
trivy image nginx:alpine

# Skannaa vain kriittiset ja korkeat haavoittuvuudet
trivy image --severity HIGH,CRITICAL nginx:alpine

# Ohita haavoittuvuudet, joihin ei ole korjausta
trivy image --severity HIGH,CRITICAL --ignore-unfixed nginx:alpine

# Epäonnistu, jos löytyy kriittisiä haavoittuvuuksia (CI/CD-portti)
trivy image --exit-code 1 --severity CRITICAL myapp:latest

# Generoi SBOM (Software Bill of Materials)
trivy image --format cyclonedx --output sbom.json myapp:latest

GitHub Actions -integraatio

Tässä toimiva esimerkki, jolla saat Trivyn pyörimään automaattisesti jokaisessa pull requestissa:

# .github/workflows/container-security.yml
name: Konttiturvallisuusskannaus
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  trivy-scan:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Rakenna Docker-kuva
        run: docker build -t myapp:${{ github.sha }} .

      - name: Trivy-haavoittuvuusskannaus
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: 'myapp:${{ github.sha }}'
          format: 'sarif'
          output: 'trivy-results.sarif'
          severity: 'CRITICAL,HIGH'
          exit-code: '1'

      - name: Lataa tulokset GitHub Securityyn
        uses: github/codeql-action/upload-sarif@v2
        if: always()
        with:
          sarif_file: 'trivy-results.sarif'

Ajonaikainen valvonta Falcolla

Mikä on Falco?

Falco on CNCF:n graduated-projekti, joka tarjoaa ajonaikaisen turvallisuusvalvonnan konteille, Kubernetesille ja isäntäkoneille. Se käyttää eBPF-teknologiaa (extended Berkeley Packet Filter) tarkkailemaan jokaista järjestelmäkutsua reaaliajassa — ja mikä parasta, ilman merkittävää suorituskykyhaittaa.

Falco havaitsee muun muassa:

  • Odottamattomat shell-kutsut kontin sisällä
  • Oikeuksien eskalaatioyritykset
  • Arkaluontoisten tiedostojen lukeminen (/etc/shadow, /etc/passwd)
  • Epätavalliset verkkoyhteydet
  • Kontin tiedostojärjestelmän muutokset

Falcon asennus ja konfigurointi

# Asennus Debian/Ubuntu-järjestelmiin
curl -fsSL https://falco.org/repo/falcosecurity-packages.asc | \
  sudo gpg --dearmor -o /usr/share/keyrings/falco-archive-keyring.gpg

echo "deb [signed-by=/usr/share/keyrings/falco-archive-keyring.gpg] \
  https://download.falco.org/packages/deb stable main" | \
  sudo tee /etc/apt/sources.list.d/falcosecurity.list

sudo apt-get update && sudo apt-get install -y falco

# Konfiguroi eBPF-ajuri (suositeltu ytimen 5.8+)
sudo falcoctl driver config --type modern_ebpf
sudo falcoctl driver install

# Käynnistä Falco
sudo systemctl enable --now falco

Mukautettujen sääntöjen kirjoittaminen

Falcon oletussäännöt ovat hyvä alku, mutta omien sääntöjen kirjoittaminen on se kohta, jossa Falco alkaa todella loistaa. Tässä pari käytännön esimerkkiä:

# /etc/falco/rules.d/kontti-saannot.yaml

# Havaitse shell-kutsu kontin sisällä
- rule: Kontin sisäinen shell-kutsu
  desc: Havaitsee, kun kontin sisällä avataan interaktiivinen shell
  condition: >
    spawned_process and
    container and
    proc.name in (bash, sh, zsh, dash) and
    proc.pname != entrypoint
  output: >
    Shell avattu kontissa
    (käyttäjä=%user.name kontti=%container.name
    kuva=%container.image.repository komento=%proc.cmdline)
  priority: WARNING
  tags: [kontti, shell]

# Havaitse arkaluontoisten tiedostojen lukeminen
- rule: Arkaluontoisten tiedostojen luku kontissa
  desc: Havaitsee /etc/shadow tai /etc/passwd lukemisen kontissa
  condition: >
    open_read and
    container and
    (fd.name = /etc/shadow or fd.name = /etc/passwd)
  output: >
    Arkaluontoinen tiedosto luettu kontissa
    (tiedosto=%fd.name kontti=%container.name
    kuva=%container.image.repository)
  priority: CRITICAL
  tags: [kontti, tiedosto, luottamuksellisuus]
# Testaa sääntöjä
sudo falco -r /etc/falco/rules.d/kontti-saannot.yaml --dry-run

# Seuraa hälytyksiä reaaliajassa
sudo falco -r /etc/falco/rules.d/kontti-saannot.yaml

# Toisessa terminaalissa: laukaise hälytys
docker exec -it mycontainer /bin/sh
# Falco raportoi: "Shell avattu kontissa"

Falcosidekick: Hälytysten reititys

Hälytykset ovat hyödyttömiä, jos kukaan ei näe niitä. Falcosidekick reitittää Falcon hälytykset yli 50 kohteeseen — Slackiin, Microsoft Teamsiin, Elasticsearch/OpenSearchiin, PagerDutyyn ja moneen muuhun.

# Asenna Falcosidekick Dockerilla
docker run -d --name falcosidekick \
  -p 2801:2801 \
  -e SLACK_WEBHOOKURL="https://hooks.slack.com/services/xxx/yyy/zzz" \
  -e SLACK_MINIMUMPRIORITY="warning" \
  falcosecurity/falcosidekick

# Konfiguroi Falco lähettämään hälytykset Falcosidekickille
# /etc/falco/falco.yaml
# http_output:
#   enabled: true
#   url: http://localhost:2801

Verkkoturvallisuus: Konttien välisen liikenteen rajoittaminen

Oletuksena saman Docker-verkon kontit voivat kommunikoida vapaasti keskenään. Tämä on merkittävä riski, joka usein jää huomaamatta: jos yksi kontti vaarantuu, hyökkääjä pääsee käsiksi muihin palveluihin samassa verkossa.

Ratkaisu on eristää palvelut omiin verkkoihinsa.

# Luo eristetyt verkot eri palveluille
docker network create --driver bridge frontend-verkko
docker network create --driver bridge backend-verkko
docker network create --driver bridge tietokanta-verkko

# Web-palvelin saa pääsyn vain frontend-verkkoon
docker run -d --name web \
  --network frontend-verkko \
  nginx:alpine

# API-palvelin yhdistää frontendin ja backendin
docker run -d --name api \
  --network frontend-verkko \
  myapp:latest
docker network connect backend-verkko api

# Tietokanta on eristetty omaan verkkoonsa
docker run -d --name postgres \
  --network tietokanta-verkko \
  postgres:16-alpine
docker network connect tietokanta-verkko api

# Nyt web ei voi suoraan tavoittaa tietokantaa

Tuotantovalmis tarkistuslista

Ennen kuin viet kontteja tuotantoon, käy tämä lista läpi. Olen itse pitänyt tätä (tai jotain hyvin samankaltaista) kirjanmerkkinä jo vuosia:

  1. Isäntäkone — Päivitä ydin ja Docker/Podman säännöllisesti. Poista tarpeettomat paketit.
  2. Daemon — Konfiguroi daemon.json (no-new-privileges, userns-remap, icc=false).
  3. Rootless — Käytä rootless-tilaa tai vähintään userns-remap-ominaisuutta.
  4. Kyvykkyydet — Pudota kaikki kyvykkyydet (--cap-drop ALL) ja lisää vain tarvittavat.
  5. Seccomp — Käytä sovelluskohtaisia seccomp-profiileja.
  6. MAC — Ota AppArmor tai SELinux käyttöön pakottavassa tilassa.
  7. Kuvat — Käytä distroless/Alpine-peruskuvia. Kiinnitä versiot digestillä.
  8. Skannaus — Integroi Trivy CI/CD-putkeen. Estä CRITICAL-haavoittuvuuksia sisältävien kuvien käyttöönotto.
  9. Ajonaikainen valvonta — Ota Falco käyttöön eBPF-ajurilla.
  10. Verkko — Eristä kontit erillisiin verkkoihin. Estä konttien välinen vapaa liikenne (icc: false).
  11. Salaisuudet — Älä koskaan tallenna salaisuuksia konttikuviin tai ympäristömuuttujiin. Käytä Docker Secrets- tai Vault-mekanismeja.
  12. Socket — Älä koskaan liitä /var/run/docker.sock konttiin. Tämä on yksi yleisimmistä virheistä, ja sen seuraukset voivat olla katastrofaaliset.

Usein kysytyt kysymykset (FAQ)

Mikä on rootless-kontti ja miksi se on tärkeä?

Rootless-kontti pyörii kokonaan ilman root-oikeuksia — sekä konttiprosessi että konttimoottori toimivat tavallisen käyttäjän oikeuksilla. Tämä on tärkeää, koska jos hyökkääjä onnistuu murtautumaan kontista ulos, hänellä ei ole root-oikeuksia isäntäkoneeseen. Podman tukee rootless-tilaa oletuksena, Docker vaatii erillisen konfiguroinnin.

Onko --privileged-lipun käyttö turvallista tuotannossa?

Lyhyt vastaus: ei. --privileged-lippu poistaa käytännössä kaikki eristysmekanismit: seccompin, AppArmorin/SELinuxin ja Linux-kyvykkyyksien rajoitukset. Etuoikeutettu kontti vastaa käytännössä suoraa pääsyä isäntäkoneeseen. Tuotannossa tätä ei pidä koskaan käyttää, ellei kyse ole hyvin erityisestä käyttötapauksesta (kuten Falco-valvontakontista), ja silloinkin se tulee kompensoida muilla suojauskeinoilla.

Miten seccomp eroaa AppArmorista konttien suojauksessa?

Seccomp rajoittaa, mitä järjestelmäkutsuja kontti voi tehdä ytimeen — se toimii ytimen rajapinnan tasolla. AppArmor puolestaan rajoittaa, mihin tiedostoihin, verkkoresursseihin ja kyvykkyyksiin prosessi pääsee käsiksi — se toimii tiedostojärjestelmän ja resurssien tasolla. Ne siis täydentävät toisiaan, ja molempia tulisi käyttää yhdessä syvyyssuuntaisen puolustuksen (defense in depth) periaatteen mukaisesti.

Kuinka usein konttikuvat tulisi skannata haavoittuvuuksien varalta?

Jokaisessa CI/CD-putken ajossa — jokainen pull request ja deploymentti. Sen lisäksi aikataulun mukaan päivittäin, vaikka koodiin ei olisi tullut muutoksia. Uusia CVE-haavoittuvuuksia löydetään jatkuvasti, ja eilen turvallinen kuva voi olla tänään haavoittuva. Trivyn --exit-code 1 -valinta muuttaa skannerin turvallisuusportiksi, joka estää haavoittuvien kuvien käyttöönoton automaattisesti.

Voiko Docker- ja Podman-kontteja ajaa samalla palvelimella?

Kyllä voi, mutta se vaatii huolellista konfigurointia. Docker ja Podman käyttävät erillisiä kuva- ja konttivarastoja, joten ne eivät suoranaisesti häiritse toisiaan. Suurin huomio on resurssien hallinta — molemmat jakavat saman ytimen ja laitteistoresurssit. Turvallisuuden (ja järjen) kannalta suositeltavampaa on kuitenkin standardoida yhteen konttimoottoriin per palvelin, jotta hallinta ja auditointi pysyvät yksinkertaisina.

Tietoa Kirjoittajasta Editorial Team

Our team of expert writers and editors.