Giriş
Bu yazı dizisine katkılarından dolayı sevgili dostum Altan Sirel ve sevgili padawan’ım Ahmet S. Külekçi’ye (özellikle ekran görüntüleri için) teşekkürlerimi borç bilirim.
Güvenlik bir yaşam biçimidir. Bu cümle aslında tüm yazılarımızın felsefesinin de merkezini oluşturuyor. Yazı dizimize başlamadan önce bir takım kavramlardan bahsetmek faydalı olacaktır. DevOps’u hiç durmaksızın yaşayan bir döngü olarak tanımlayacak olursak DevSecOps da güvenliğin yazılım ve operasyon süreçlerine bir yaşam biçimi olarak dahil olmasıdır diyebiliriz.
Docker Container Güvenliği yazı dizisi ile amacımız, sanallaştırma dünyasının “2.0” versiyonu olarak görülen ve yeni nesil sanallaştırma teknolojisi olarak bahsedilen container teknolojilerinin en ünlü ürünü olan Docker üzerinden güvenliğin nasıl sağlanacağını detaylı olarak incelemektir.
İlk olarak Container teknolojisinin genel mantığından bahsettikten sonra aslında güvenliğin her katmanda sağlanmasının nasıl bir yaklaşım olduğuna değineceğiz. Daha sonra Docker Security konumuzu üç ana bölüme ayırıp inceleyeceğiz. Birinci bölümde Docker Güvenlik Önerilerini inceledikten sonra ikinci bölümümüzde Docker Enterprise Güvenlik Önerilerine geçeceğiz. Ve son olarak üçüncü bölümümüzde tüm docker projelerinizde kullanabileceğiniz Docker Security Checklist’ini bir excel halinde içerisinde Gantt Table ile birlikte sizlerle paylaşacağız.
Her ne kadar yazının üç ana bölümü olacak olsa da yazı üç parttan daha fazla olacak. O yüzden yazının üç ana bölümü ile yayınlanan partları karıştırmayalım.
Docker ve Container Teknolojisine Bakış
Bu yazı dizisinde amacımız Docker’ın veya Container teknolojisinin ne olduğunu anlatmak değil. Bunun için İngilizce ve Türkçe yüzlerce harika makale bulabilirsiniz. Biz, Docker ve Container teknolojilerine güvenlik merkezi ile yaklaşacağız.
Teknolojinin emekleme dönemleri sayılabilecek zamanlarda yazılımlar direkt olarak fiziki sunucularda koşturulurdu. Sanallaştırma teknolojisinin gelişmesiyle birlikte bir fiziki sunucu içerisinde bulunan sanal makinelerde birden fazla yazılım kullanılabilir hale geldi. Sanal makineler (VM) pratikte üzerinde konak oldukları işletim sistemleri kadar güvenlidir. Bir VM üzerinde çalıştırılan yazılımdaki zafiyetten faydalanan kişi tüm sunucuya sızabilir. En kötü senaryo ne olabilir diye düşündüğümüzde VM Escape adı verilen ve sanal makine atlatılarak direkt olarak hipervizör üzerinde işlemlerin yapıldığı senaryo aklımıza gelebilir. Nitekim 2015 yılında CEN-2015–3456 kodu ile VENOM olarak adlandırılan zafiyet sömürü yöntemi ile ana bilgisayarda çalışan diğer sanal makinelere erişim sağlanmış oldu.
Bu durumda artık teknolojinin bir adım daha öteye gitmesi gerektiği zaten anlaşılmıştı ve “Container” denilen yapılar devreye girdi. Docker gibi sistemler sayesinde ana bilgisayar ile olan bağın diğer sanal makinelere erişilmesi problemi büyük ölçüde çözülmüş oldu.
Aslında burada sadece bir teknoloji değil aynı zamanda bir felsefe de yatıyor. Bu felsefeyi anlamak konunun belki de teknik detayını öğrenmekten daha önemli. Çünkü teknik detaylara hâkim olunsa dahi yazılım geliştirme süreçlerine en başından dahil olmayan güvenlik yaklaşımları belirli bir süre sonra problem yaşamaya başlayacaktır.
Güvenliği merkezine alan DevSecOps, SSDLC gibi yaklaşımlardan önce yazılım geliştirme süreçleri aşağıdaki gibi ilerliyordu.
Yukarıda görmüş olduğunuz yaklaşımın adı Waterfall. Uzun yıllar yazılım dünyasında en çok kullanılan ve hatta günümüzde de halen kullanılan bir model. Peki güvenlik bunun neresinde? İşte sorun burada başlıyor. Bu yaklaşımda güvenliği her aşamaya implemente etmenin zorluğu akışın tamamen değişmesine sebep olmuştur.
DevOps olarak başlayan bu yeni felsefe günümüzde artık DevSecOps olarak da adını sıkça duyurmaya başladı. Yazılım geliştirme süreçlerindeki Continuous Integration ve Continuous Deployment/Delivery aşamasının sekteye uğramadan her bir adımda güvenliğin var olması bu felsefenin ana fikrini oluşturuyor.
Akademik dilimizi bir süre kenara bırakalım ve biraz daha basitleştirerek olayı izah etmeye çalışalım.
İkinci Dünya savaşı sonrasında ekonominin toparlanmaya çalıştığı dönemlerde ticaret küreselleşiyordu. Bu küreselleşmenin de etkisiyle taşımacılıkta bir rampa atlama zamanının geldiği hissedildi. Karanlık savaş zamanından çıkan insanlar ülkeler arası taşımacılıkta bir standarda ihtiyaç duymaya başladı. İşte tam bu aşamada Dünya Taşımacılık Konseyi (evet böyle bir konsey varmış ben de bilmiyordum) konteyner standardını duyurdu. Artık tüm taşımacılık yöntemlerinin tamamında ölçüleri tüm dünyaca kabul edilmiş ve farklı ölçülerde olan bu konteynerler kullanılacaktı. Bu sayede maliyetler düştü, taşımacılık çok daha kolay, esnek ve hızlı bir hale gelirken her şeyden önemlisi taşımacılık daha güvenli bir hale gelmişti.
Peki Docker da aslında taşımacılıkta yaşanan bu gelişmenin benzeri bir ürün değil midir?
VM ve Konteyner teknolojisi arasındaki farka aşağıdaki görselden bakabiliriz.
Teoride hem hızlı hem daha az maliyetli hem de güvenli olacak olan konteyner teknolojisi düşünüldüğü kadar güvenli mi?
Bir sistemde çalışan konteynerlerin sayısı arttıkça, içerdiği uygulamalardan birinin container “breakout” adı verilen bir ihlale yol açma olasılığı da artar.
Docker, konteynerler arasında bir düzeyde kaynak ve işlem yalıtımı sağlarken, konteyner içinde root olarak çalışan bir işlemin, çekirdek alt sistemleri ve aygıtlarıyla doğrudan iletişim halinde ana bilgisayar sisteminde root olarak çalıştığı gerçeğini eklerseniz felaket senaryoları çizmenize neden olacak durumları görebilirsiniz.
Bu problemlerin önüne geçmek için birçok otomatize araç olsa da halen bir standart ve tam çözüm üretebilen bir aracın varlığı söz konusu değildir. Bu nedenle Docker konfigürasyonlarının A-Z’ye doğru (doğru kime göre neye göre dediğinizi duyar gibiyim) yapılması ve bunların kontrol edildiği bir mekanizmanın kurulması çok önemlidir.
Yukarıdaki iki paragrafın özeti ise şudur: Güvenlik sağlayalım derken önümüze gelen her şeyi root yetkisi ile çalıştırıp şirketimizin güvenlik ekibine kalp krizi geçirtmek üzereyiz. 😊
Unutulmaması gereken altın cümle: “Docker bir güvenlik ürünü değildir.”
Yazı dizimizde tamamen CIS tarafından yayınlanan CIS Docker Benchmark v1.2.0'ı baz aldık. Ayrıca eklemeler yaptığımız kısımlar için ilgili yazının ilgili part’ına kaynaklar kısmına eklemeler yaptık. Daha fazla bilgiye ihtiyacı olanlar kaynaklar kısmını inceleyebilir.
NOT: Kaynaklar kısmında birçok önemli ve değerli makaleyi sizlerle paylaşıyoruz. İlgili tavsiyelerin içeriği hakkında daha derine girmek isteyenler kaynakları inceleyebilirler.
1.1. Genel Konfigürasyonlar
Spesifik konfigürasyonlara geçmeden önce özellikle belirtilmesi gereken bir konu var. Yazılım geliştiricisi olmak bazı (iyi veya kötü) alışkanlıkların kazanılmasına sebep oluyor. Bunlardan birisi de eğer bir şey çalışıyorsa onun versiyonunun güncellenmesinden çekinilmesidir. Ancak güncellemelerin sadece fonksiyonel iyileştirmeler, bugfixler veya yeni feature’lar olmadığını aynı zamanda o güncellemelerin güvenlik iyileştirmeleri içerebileceğini unutmamak gerekiyor.
Kısacası mümkün olan her senaryoda en güncel (en stabil olan) versiyonu kullanmak güvenlik için bir ön şarttır.
Bir diğer konu ise Docker’ın üzerinde koştuğu işletim sisteminde gerekli güncellemelerin ve doğru güvenlik konfigürasyonlarının yapılmasıdır. Docker, üzerinde koştuğu işletim sisteminin güvenli olduğu kadar güvenli olacaktır.
Bu iki konudan da bahsettikten sonra artık yolculuğumuza başlayabiliriz.
1.2. Linux Hostlar için Spesifik Konfigürasyonlar
Docker’ın hostu olarak en çok kullanılan işletim sistemlerinden biri olan Linux konfigürasyonlarını inceleyelim.
1.2.1. Her bir konteyner için ayrı partition ayrılması
Varsayılan olarak tüm Docker konteynerları ve onların verileri ile meta verileri linuxta /var/lib/docker dizininde bulunur. Eğer varsayılan olarak bunu bu şekilde bırakırsanız tüm konteynarların verilerine tek bir noktadan erişilmesi tehlikesi ile karşı karşıya kalırsınız. Aynı zamanda yine varsayılan olarak Docker imajlarının da burada depolandığını düşünürsek bu dizin sizin storage kapasitenize bağlı olarak hızlı bir şekilde dolabilir ve hem ana makinenin hem de Docker’ın kullanılamaz hale gelmesine sebep olabilir.
Hem güvenlik hem de storage optimizasyonu için Docker dosyalarını ayrı bir mantıksal birimde oluşturmalısınız.
Nasıl kontrol ederim?
grep ‘/var/lib/docker\s’ /proc/mounts
Yukarıdaki komutu Docker’ı kurduğunuz ana makinenizin terminalinde çalıştırdığınızda size /var/lib/docker mount noktası için partition detaylarını verecektir.
Kontrol için bir diğer komut ise şudur:
mountpoint — “$(docker info -f ‘{{ .DockerRootDir }}’)”
Bu komut ise size root dizininin yapılandırılmış bir mount noktası olup olmadığını gösterecektir.
Eğer ilk kurulum aşamasında bunu yapmak istiyorsanız /var/lib/docker mount noktası için ayrı bir partition oluşturmalısınız. Ancak hali hazırda çalışan bir sistemde bunu yapmak istiyorsanız Linux LVM’i kullanarak bunu gerçekleştirebilirsiniz.
1.2.2. Docker Daemon kontrolünün belirli kullanıcılara verilmesi
Docker, konteynerın erişim haklarını sınırlamadan ana makine ile guest konteyner arasında dizin paylaşmamıza olanak sağlar. Bu aynı zamanda direkt olarak bir konteyner oluşturup ana makinenin / dizinini konteyner ile eşleştirebileceğimiz anlamına gelir. Docker Daemon varsayılan olarak root ve docker grubuna ait kullanıcılar tarafından kontrol edilebilir durumdadır.
Bu durumda konteyner herhangi bir kısıtlama olmadan ana makinemizin dosya sisteminde değişiklikler yapabilir. Eğer docker grubunun bir üyesi olan kullanıcıysanız hak yükseltme yapabilir ve ana makinede root dizini ile eşleşen bir konteyner başlatabilirsiniz. Aslında ne kadar korkutucu bir senaryo değil mi?
Aşağıdaki komut ile docker grubunda olan kullanıcıları görüntüleyebilirsiniz. Burada sadece olması gereken kullanıcıların olmasına çok dikkat etmelisiniz.
getent group docker
Bu komutu çalıştırdıktan sonra incelediğiniz kullanıcılar arasında trusted olmayanları silmelisiniz. Ayrıca hassas veri içerdiğini bildiğiniz dizinleri ana makine ile konteyner arasında eşleştirmemelisiniz.
1.2.3. Docker Daemon için denetim konfigürasyonu
Ana makinenin Linux dosya sistemi ve sistem çağrılarını monitör etmek ve denetlemek önemlidir. Bununla birlikte aynı öneme sahip bir diğer konu da Docker Daemon’ın denetlenmesidir. Docker Daemon root ayrıcalıklarıyla çalıştığı için faaliyetlerini vekullanımını denetlemek çok büyük öneme sahiptir. Varsayılan olarak Docker daemon’ın audit logu tutmuyor. Bunu bizim ayarlamamız gerekecek.
/etc/audit/audit.rules dosyasına aşağıdaki satırı ekleyelim:
-w /usr/bin/dockerd -k docker
Bu işlemi gerçekleştirdikten sonra audit daemon’ı yeniden başlatmamız gerekiyor:
service auditd restart
Peki audit kuralının olup olmadığını nasıl doğrulayabiliriz? Aşağıdaki komut da bunun için:
auditctl -l | grep /usr/bin/dockerd
Burada dikkat edilmesi gereken önemli bir husus daha var. Bu şekilde audit logları tutmak çok büyük dosyaların oluşmasına ve sistemin şişmesine neden olabilir. Bu nedenle periyodik olarak bu logların rotate edilmesini sağlayarak arşivlemelisiniz. Ayrıca diğer kritik bölümlerin dolmaması için de audit loglarına ayrı bir bölüm oluşturulmalıdır.
1.2.4. Docker dizinleri ve dosyaları için denetim konfigürasyonu
Linux sistem çağrılarını denetliyoruz. Linux dosya sistemini de mutlaka denetliyoruz. Peki ya Docker ile ilgili tüm dosya ve dizinleri de denetliyor muyuz? Eğer tüm sistemi denetliyorsak mantıken denetliyoruz diyebiliriz ancak burada ayrı parantez açmanın ve bu konuyu ayrıca kontrol etmenin de faydası olacağını düşünüyoruz.
Docker arka plandaki çalışmalarını root ayrıcalıklarıyla gerçekleştirir. Bu çalışmaları gerçekleştirmesi bazı dizinlere bağlıdır. Örneğin /var/lib/docker dizini gibi. Bu kısımda hangi dizin ve dosyaları denetlememiz gerektiğine ve bunu nasıl gerçekleştireceğimize bakalım. Ayrıca Docker’ın varsayılan birçok denetimi denetimi yapmadığını da ekleyelim.
NOT: Bu bölümde audit.rules dosyasına eklenen satırlar sonrası Audit Daemon’ı yeniden başlatmamız gerekiyor. Eklemeniz gereken tüm satırları ekledikten sonra aşağıdaki komut ile Audit Daemon’ı yeniden başlatabilirsiniz:
service auditd restart
/var/lib/docker
Bu dizin konteynerlar hakkındaki tüm bilgileri içerir. Bu nedenle bu dizin ve dosyaları denetlemek gerekir.
Bu denetimi gerçekleştirmek için /etc/audit/audit.rules dosyasına aşağıdaki satırı eklememiz yeterli olacaktır.
-w /var/lib/docker -k docker
Eğer /var/lib/docker dizini için denetim yapıp yapmadığımızı kontrol etmek istersek aşağıdaki komut ile bunu gerçekleştirebiliriz:
auditctl -l | grep /var/lib/docker
/etc/docker ve /etc/default/docker
Bu dizin Docker Daemon ile Docker Client arasındaki TLS iletişimi için kullanılan çeşitli sertifika ve key’leri içeriyor. Bu nedenle denetleme listemize bu dizini de eklemeliyiz.
Bu denetimi gerçekleştirmek için /etc/audit/audit.rules dosyasına aşağıdaki satırı eklememiz yeterli olacaktır.
-w /etc/docker -k docker
/etc/default/docker dosyasını denetlemek için:
-w /etc/default/docker -k docker
/usr/lib/systemd/system/docker.service
Docker Daemon parametreleri bir kullanıcı tarafından değiştirildiğinde docker.service dosyası oluşur ve içerisinde çeşitli parametreleri barındırır. Bu dosyayı denetlemek yapılmış olan değişiklikleri kontrol etmek açısından önemlidir.
Bu denetimi gerçekleştirmek için /etc/audit/audit.rules dosyasına aşağıdaki satırı eklememiz yeterli olacaktır.
-w /usr/lib/systemd/system/docker.service -k docker
Burada yapacağımız kontrolde iki aşama düşünebiliriz. Birincisi için aşağıdaki komutu yazalım:
systemctl show -p FragmentPath docker.service
Bu komut sonucunda eğer docker.service dosyası diye bir dosya yoksa iki seçenek var demektir. Ya herhangi bir değişiklik yapılmadığı için böyle bir dosya oluşmamıştır ya da audit rule çalışmıyordur. Bundan emin olmak için admin haklarıyla bir Docker Daemon parametrelerinde bir değişiklik yaparak tekrar yukarıdaki komutu yazabiliriz.
Veya ikinci yöntem olarak audit rule kontrolü yapabiliriz:
auditctl -l | grep docker.service
docker.socket
Docker Daemon için önemli parametrelere sahip bir diğer dosya da docker.socket dosyası. Tıpkı docker.service’de olduğu gibi bu dosyayı da denetlememiz faydalı olacaktır. Docker ilk kurulduğunda bu dosya ortalarda olmayacağı için yine varsayılan olarak denetimi yapılmamakta.
Bu denetimi gerçekleştirmek için /etc/audit/audit.rules dosyasına aşağıdaki satırı eklememiz yeterli olacaktır.
-w /usr/lib/systemd/system/docker.socket -k docker
Docker.service için bahsettiğimiz kontrol konusu burada da aynı şekilde geçerli. Bazen docker.socket diye bir dosya olmayabilir. Bu nedenle yine aynı mantıkla aşağıdaki komutları docker.service’de olduğu gibi kullanabilirsiniz.
systemctl show -p FragmentPath docker.socketauditctl -l | grep docker.socket
Bu bölümde denetlememiz gereken üç farklı dosya/klasörümüz daha kaldı. Bunlara da göz atalım:
/etc/docker/daemon.json
/usr/bin/containerd
/etc/sbin/runc
Daemon.json dosyası docker daemon konfigürasyon dosyamız oluyor. Containerd runc v.b. metaları kontrol etmek için kullanılan daemon’dır. Runc ise OCI spesifikasyonuna göre konteynerleri spawn ve run etmek için kullanılan bir CLI aracıdır. Bu 3 cümle direkt olarak neden denetleme yapmamız gerektiğiniz bize anlatıyor.
Bu üç dosyamızız da denetim listemize almak için /etc/audit /audit.rules dosyasına aşağıdaki satırları eklememiz yeterli olacaktır.
-w /etc/docker/daemon.json -k docker-w /usr/bin/containerd -k docker-w /usr/sbin/runc -k docker
Kontrol etmek için ise:
auditctl -l | grep /etc/docker/daemon.jsonauditctl -l | grep /usr/bin/containerdauditctl -l | grep /usr/sbin/runc
Bu komutları kullanabilirsiniz.
Bir önceki konuda bahsettiğimiz gibi audit logları çok büyük dosyaların oluşmasına ve sistemin şişmesine neden olabileceği için periyodik olarak bu logların rotate edilmesini sağlayarak arşivlemeyi unutmamalıyız.
Tüm bunları gerçekleştirdiğimize göre bir sonraki yazımızda Docker Daemon konfigürasyonlarına geçebiliriz demektir.
Sorularınız ve düzeltme önerileriniz için iletişim: serhanw@pm.me
Kaynaklar:
CIS Docker Benchmark v1.2.0–07–29–2019
http://blog.docker.com/2014/06/why-you-dont-need-to-run-sshd-in-docker/
http://blog.scalock.com/new-docker-security-features-and-what-they-mean-seccomp-profiles
http://container-solutions.com/content/uploads/2015/06/15.06.15_DockerCheatSheet_A2.pdf
http://craiccomputing.blogspot.in/2014/09/clean-up-unused-docker-containers-and.html
http://daviddaeschler.com/2014/12/14/centos-7rhel-7-and-docker-containers-on-boot/
http://docs.docker.com/reference/commandline/cli/#run
http://docs.fedoraproject.org/en-US/Fedora/13/html/Security-Enhanced_Linux/
http://jpetazzo.github.io/assets/2015-03-05-deep-dive-into-docker-storage-drivers.html#1
http://man7.org/linux/man-pages/man2/setgid.2.html
http://man7.org/linux/man-pages/man2/setuid.2.html
http://man7.org/linux/man-pages/man7/namespaces.7.html
http://man7.org/linux/man-pages/man7/pid_namespaces.7.html
http://man7.org/linux/man-pages/man7/user_namespaces.7.html
http://muehe.org/posts/switching-docker-from-aufs-to-devicemapper/
https://access.redhat.com/security/team/key
https://arxiv.org/pdf/1501.02967
https://avicoder.me/2016/07/22/Twitter-Vine-Source-code-dump/
https://blog.docker.com/2015/11/docker-trusted-registry-1-4/
https://blog.docker.com/2016/05/docker-security-scanning/
https://docs.docker.com/datacenter/ucp/2.2/guides/admin/configure/external-auth/
https://docs.docker.com/datacenter/ucp/2.2/guides/admin/configure/run-only-the-images-you-trust/
https://docs.docker.com/datacenter/ucp/2.2/guides/admin/configure/use-your-own-tls-certificates/
https://docs.docker.com/datacenter/ucp/2.2/reference/cli/install/#description
https://docs.docker.com/develop/develop-images/build_enhancements/
https://docs.docker.com/docker-cloud/builds/image-scan/
https://docs.docker.com/edge/engine/reference/commandline/dockerd/
https://docs.docker.com/edge/engine/reference/commandline/dockerd/#default-ulimits
https://docs.docker.com/edge/engine/reference/commandline/dockerd/#options
https://docs.docker.com/ee/dtr/admin/configure/set-up-vulnerability-scans/
https://docs.docker.com/ee/ucp/admin/configure/set-session-timeout/
https://docs.docker.com/ee/ucp/authorization/
https://docs.docker.com/ee/ucp/user-access/cli/
https://docs.docker.com/engine/admin/configuring/
https://docs.docker.com/engine/admin/live-restore/
https://docs.docker.com/engine/admin/logging/overview/
https://docs.docker.com/engine/admin/runmetrics/
https://docs.docker.com/engine/admin/systemd/
https://docs.docker.com/engine/extend/plugins_authorization/
https://docs.docker.com/engine/installation/
https://docs.docker.com/engine/reference/builder/#healthcheck
https://docs.docker.com/engine/reference/builder/#/onbuild
https://docs.docker.com/engine/reference/commandline/cli/#environment-variables
https://docs.docker.com/engine/reference/commandline/cli/#notary
https://docs.docker.com/engine/reference/commandline/dockerd/#access-authorization
https://docs.docker.com/engine/reference/commandline/dockerd/#daemon-configuration-file
https://docs.docker.com/engine/reference/commandline/dockerd/#daemon-socket-option
https://docs.docker.com/engine/reference/commandline/dockerd/#daemon-user-namespace-options
https://docs.docker.com/engine/reference/commandline/dockerd/#default-cgroup-parent
https://docs.docker.com/engine/reference/commandline/dockerd/#storage-driver-options
https://docs.docker.com/engine/reference/commandline/exec/
https://docs.docker.com/engine/reference/commandline/pull/
https://docs.docker.com/engine/reference/commandline/rmi/
https://docs.docker.com/engine/reference/commandline/run/#mount-tmpfs-tmpfs
https://docs.docker.com/engine/reference/commandline/run/#options
https://docs.docker.com/engine/reference/commandline/run/#restart-policies-restart
https://docs.docker.com/engine/reference/commandline/secret/
https://docs.docker.com/engine/reference/commandline/swarm_init/
https://docs.docker.com/engine/reference/commandline/swarm_init/#--data-path-addr
https://docs.docker.com/engine/reference/commandline/swarm_init/#--listen-addr
https://docs.docker.com/engine/reference/commandline/swarm_unlock-key/
https://docs.docker.com/engine/reference/commandline/swarm_update/#examples
https://docs.docker.com/engine/reference/run/#ipc-settings-ipc
https://docs.docker.com/engine/reference/run/#network-settings
https://docs.docker.com/engine/reference/run/#pid-settings-pid
https://docs.docker.com/engine/reference/run/#security-configuration
https://docs.docker.com/engine/reference/run/#specify-custom-cgroups
https://docs.docker.com/engine/reference/run/#uts-settings-uts
https://docs.docker.com/engine/reference/run/#volume-shared-filesystems
https://docs.docker.com/engine/security/apparmor/
https://docs.docker.com/engine/security/https/
https://docs.docker.com/engine/security/seccomp/
https://docs.docker.com/engine/security/security/#docker-daemon-attack-surface
https://docs.docker.com/engine/security/security/#other-kernel-security-features
https://docs.docker.com/engine/security/trust/content_trust/
https://docs.docker.com/engine/security/userns-remap/
https://docs.docker.com/engine/swarm/admin_guide/#/add-manager-nodes-for-fault-tolerance
https://docs.docker.com/engine/swarm/admin_guide/#recover-from-disaster
https://docs.docker.com/engine/swarm/how-swarm-mode-works/pki/#rotating-the-ca-certificate
https://docs.docker.com/engine/swarm/manage-nodes/
https://docs.docker.com/engine/swarm/swarm_manager_locking/
https://docs.docker.com/engine/tutorials/dockervolumes/
https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/#add-or-copy
https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/#run
https://docs.docker.com/engine/userguide/networking/
https://docs.docker.com/engine/userguide/networking/default_network/binding/
https://docs.docker.com/engine/userguide/networking/overlay-security-model/
https://docs.docker.com/engine/userguide/storagedriver/
https://docs.docker.com/engine/userguide/storagedriver/selectadriver/#supported-backing-filesystems
https://docs.docker.com/registry/insecure/
https://docs.docker.com/storage/bind-mounts/#configure-bind-propagation
https://docs.docker.com/userguide/dockerimages/
https://forums.docker.com/t/command-to-remove-all-unused-images/20/8
https://forums.docker.com/t/docker-in-docker-vs-mounting-var-run-docker-sock/9450/2
https://fralef.me/docker-and-iptables.html
https://github.com/docker/docker/blob/master/profiles/seccomp/default.json
https://github.com/docker/docker-ce/blob/master/components/packaging/deb/systemd/docker.socket
https://github.com/docker/docker-ce/releases/latest
https://github.com/docker/docker/issues/14856
https://github.com/docker/docker/issues/21109
https://github.com/docker/docker/issues/22741
https://github.com/docker/docker/issues/22870
https://github.com/docker/docker/issues/24253
https://github.com/docker/docker/issues/2918
https://github.com/docker/docker/issues/3313
https://github.com/docker/docker/issues/7906
https://github.com/docker/docker/issues/8093
https://github.com/docker/docker/issues/9054
https://github.com/docker/docker/pull/11109
https://github.com/docker/docker/pull/12648
https://github.com/docker/docker/pull/16609
https://github.com/docker/docker/pull/18697
https://github.com/docker/docker/pull/20662
https://github.com/docker/docker/pull/20727
https://github.com/docker/docker/pull/26276
https://github.com/docker/docker/pull/4572
https://github.com/docker-library/httpd/blob/12bf8c8883340c98b3988a7bade8ef2d0d6dcf8a/2.4/Dockerfile
https://github.com/moby/moby/issues/33938
https://github.com/moby/moby/pull/20727
https://github.com/moby/moby/pull/29984
https://github.com/moby/moby/pull/32717
https://github.com/moby/moby/releases/latest
https://github.com/nyantec/narwhal
https://github.com/opencontainers/runc
https://github.com/progrium/busybox
https://github.com/projectatomic/atomic-site/issues/269
https://github.com/twistlock/authz
https://github.com/YungSang/fedora-atomic-packer/blob/master/oem/docker.socket
https://goldmann.pl/blog/2014/09/11/resource-management-in-docker/
https://lwn.net/Articles/475362/
https://lwn.net/Articles/475678/
https://raesene.github.io/blog/2016/03/06/The-Dangers-Of-Docker.sock/
https://registry.hub.docker.com/
https://titanous.com/posts/docker-insecurity
https://www.andreas-jung.com/contents/on-docker-security-docker-group-considered-harmful
https://www.kernel.org/doc/Documentation/filesystems/sharedsubtree.txt
https://www.kernel.org/doc/Documentation/prctl/no_new_privs.txt
https://www.kernel.org/doc/Documentation/prctl/seccomp_filter.txt
https://www.projectatomic.io/docs/docker-storage-recommendation/
https://zeltser.com/security-risks-and-benefits-of-docker-application/
http://windsock.io/the-docker-proxy/
http://www.livewyer.com/blog/2015/02/24/slimming-down-your-docker-containers-alpine-linux
http://www.oreilly.com/webops-perf/free/files/docker-security.pdf
http://www.projectatomic.io/blog/2015/12/making-docker-images-write-only-in-production/