Docker Notlarım
Docker’a giriş notlarım. Bu notlar Özgür Öztürk’ün Docker Eğitiminden aldığım notlarımdır.
#Container oluşturulduktan sonra date uygulaması çalıştırılacak. Container başka bir uygulama ile başlatılacak.
docker container run --name deneme httpd date
#Container'i arka planda çalıştırmak için
docker container run -d deneme2
#Container içerisinde komut çalıştırmak için "exec"
docker container exec 94ef4e4f89 ls
#Çalışan container'a nasıl bağlanılır
docker container exec -it deneme1 sh
#Bir sanal makine ile Container'in farkı; Container'de kernel yoktur, üzerinde çalıştığı hostun kernel'ini kullanır.
#Container ile ilgili daha fazla bilgi edinmek için
docker container inspect deneme1
docker network inspect bridge
docker image inspect fedora
#Container'a bağlanıp değişiklik yapılması pek önerilmez. Bazılarına bağlanılmaz bile.
#Container loglarına bakmak için
docker container logs deneme1
#Container loglarını zaman damgalarıyla göstermek için
docker container logs -t deneme1
#Container loglarındaki son birkaç satırı görmek için
docker container logs --tail 5 deneme1
#Container loglarını canlı görmek için
docker container logs -f deneme1
#Container'ın kaynaklarına bakmak için
docker container top webserver
docker container stats webserver
docker stats
#Container'ları sınırlamadığımız sürece host makinedeki kaynakları sınırsız kullanabilir.
Bu container'ların kaynaklarını kısıtlayabiliriz.
#Container'ın memory kısıtlaması için
docker container run -d --name deneme3 --memory=1G httpd
docker container run -d --name deneme3 --memory=500K httpd
#CPU kısıtlaması için iki yol vardır
#Container sadece 1 core kullanabilecek random olarak
docker run -d --name cpukisit --cpus="1" httpd
#Container 2 ve 8 nolu core'ları kullanabilecek
docker container run -d --name cpukisit2 --cpuset-cpus="2,8" httpd
#Container'de swap belirlemek için
docker run -d --name swap --memory-swap=1G httpd
#Tüm containerları topluca silmek için
docker container prune
Docker Volume:
#Volume'lar hos makinede bir klasör olarak durur. Container' bağlanan bir volume'da bir değişiklik yapılırsa host makinedeki o volume klasöründe de etkili olacaktır.
#Volume oluşturma
docker volume create deneme
#Volume'ları listeleme
docker volume ls
#Volume'ları detaylı inceleme
docker volume inspect deneme
#Volume'ı container'a bağlama
docker run -it --name denemevolume -v deneme:/osman httpd sh
#Bir volume'u birçok container'a bağlayabiliriz
#Volume'ü read only bağlamak için
docker run -it --name con5 -v deneme:/test1:ro alpine sh
#Host makinedeki herhangi bir klasörü de container'a volume gibi bağlayabiliriz. Buna da bind mount denir.
docker run -it --name deneme -p 83:80 -v /home/ssnrshnn/deneme:/usr/local/apache2/htdocs httpd
#Container'de volume'nin bağlanacağı yer yok ise kendisi yaratır.
#Bir volume'u birçok container'a bağlayabiliriz
#Production'da Volume'ler ortak bir storage cihazda oluşturulur.
Environment Variables:
#Environment variable girmek için; bu env'leri container içinden kontrol de edebiliriz.
docker run -it -e mysqlserver="server.ssnrshnn.com:3306" -e mysqladmin="admin" -e mysqlpassword="passwd123@" ubuntu bash
root@5173946588a5:/# printenv
#Toplu olarak environment variable tanımlamak için bir env list oluşturur onu da aşağıdaki komutla topluca container'a tanımlayabiliriz.
docker container run -it --env-file ./env.list ubuntu bash
Drivers:
Network Drivers:
- Bridge (Default) (172.17.0.0/16)
- Host
- Macvlan
- None
- Overlay
Networkleri listeleme
docker network ls
Bir network driver'ının detaylarına bakmak için
docker network inspect bridge
Bridge Network Driver:
Bir network oluşturma
docker network create --driver bridge denemenet
Network'ün detaylarına bakma
docker network inspect denemenet
Oluşturulan network'ü container'a bağlama
docker run -it --network=denemenet busybox sh
ip a
Subnet belirleyerek bir network driver oluşturma
docker network create --driver bridge --subnet=192.168.10.0/24 --gateway=192.168.10.1 denemenet2
Default bridge network driver'ında DNS çözümlemesi kapalıdır. Container'lar birbirlerine hostname ile ulaşamazlar.
Fakat daha sonradan oluşturduğumuz bridge network driverlarında ulaşabilirler
Host Network Driver:
Hostun network driver'ını kullanır. Host'ta çalışan bir process gibi çalışır. Htop ile bakarsak ilgili process'i görürüz.
Host network driver'ının detaylarına bakmak için
docker network inspect host
Host network'ü container'a bağlama
docker run -it --network=host busybox sh
ip a
MacVlan Network Driver:
Vlan yapabilme özelliği olan network driver'ıdır.
None Network Driver:
Container hiçbir şekilde networke bağlanmasın driver'ı olmasın istenirse kullanılır.
None network'ü container'a bağlama
docker container run -it --name den2 --network=none busybox sh
ip a
Docker Hub:
Hali hazırda olan bir imajı kendimiz de tag'leyebiliriz.
docker image tag httpd:latest soner4444/deneme:latest
Image'ı Docker Hub'a göndermek istersek
docker image push soner4444/deneme:latest
Docker Hub'a CLI'den login olmak için
docker login -u soner4444
Docker Image Oluşturma:
Dockerfile - 1:
Docker’a özgü bir dil formatı ile conterner’a ne olacağını söylediğimiz dosyadır. Dockerfile’ı iyi dizayn etmemiz gerekiyor bekleme sürelerini minimalize etmek için. Değişiklik olan kısımları dosyanın altına doğru yazmamız gerekir ki Cache mekanizmasını daha efektif kullanılabilsin.
Instruction | Description |
---|---|
ADD | Add local or remote files and directories. |
ARG | Use build-time variables. |
CMD | Specify default commands. |
COPY | Copy files and directories. |
ENTRYPOINT | Specify default executable. |
ENV | Set environment variables. |
EXPOSE | Describe which ports your application is listening on. |
FROM | Create a new build stage from a base image. |
HEALTHCHECK | Check a container’s health on startup. |
LABEL | Add metadata to an image. |
MAINTAINER | Specify the author of an image. |
ONBUILD | Specify instructions for when the image is used in a build. |
RUN | Execute build commands. |
SHELL | Set the default shell of an image. |
STOPSIGNAL | Specify the system call signal for exiting a container. |
USER | Set user and group ID. |
VOLUME | Create volume mounts. |
WORKDIR | Change working directory. |
#Oluşturulacak imajın hangi imajdan oluşturulacağını belirten talimat.
#Dockerfile içerisinde geçmesi mecburi tek talimat budur. Mutlaka olmalıdır.
FROM imaj:tag
FROM ubuntu:20.04
#İmaj oluşturulurken shell'de bir komut çalıştırmak istersek bu talimat kullanılır.
RUN apt-get update
RUN apt-get install isc-dhcp-server
#Klasör değiştirmek istersek bu talimat kullanılır. cd ile aynı mantıktadır. Bunu yapmak için RUN'da kullanılır fakt kullanılmamalıdır çünkü eğer klasör yoksa RUN ile yaptığımızda klasör yaratmaz hata alırız. Fakat WORKDIR ile yaparsak, klasör olmasa bile yaratılır.
WORKDIR /usr/src/app
#İmaj içine dosya veya klasör kopyalamak için kullanılır.
COPY /source /user/src/app
#Bu imajdan oluşturulacak containerların hangi portlar üstünden erişilebileceğini yani hangi portların yayınlanacağını bu talimatlarla belirtebilirsiniz.
EXPOSE 80/tcp
#Bu imajdan container yaratıldığı zaman varsayılan olarak çalıştırmasını istediğiniz komutu bu talimat ile belirleyebilirsiniz. Bu da mutlaka olması gerekir.
CMD java merhaba
#Bu talimat ile Docker'a bir container'ın hala çalışıp çalışmadığını kontrol etmesini söyleyebiliriz. Docker varsayılan olarak container içerisinde çalışan ilk process'i izler ve o çalıştığı sürece container çalışmaya devam eder. Fakat process bile onun düzgün işlem yapıp yapmadığına bakmaz. HEALTHCHECK ile buna bakabilme imkanına kavuşuruz.
HEALTHCHECK --interval=5m --timeout=3s CMD curl -f http://localhost/ || exit 1
#Gireceğimiz komutları hangi kullanıcı ile çalıştırmasını istiyorsak bu talimat ile onu seçebiliriz.
USER poweruser
# İmaj metadata'sına key=value şeklinde değer çiftleri eklemek için kullanılır. Örneğin team=development şeklinde bir etiket eklenerek bu imajın development ekibinin kullanması için yaratıldığı belirtilebilir.
LABEL version:1.0.8
#COPY Aynı işi yapar yani dosya ya da klasör kopyalarsınız. Fakat ADD bunun yanında dosya kaynağının bir url olmasına da izin verir. Ayrıca ADD ile kaynak olarak bir .tar dosyası belirtilirse bu dosya imaja .tar olarak sıkıştırılmış haliyle değil de açılarak kopyalanır.
ADD https://wordpress.org/latest.tar.gz /temp
#Imaj içinde environment variable tanımlamak için kullanılır
ENV TEMP_FOLDER="/temp"
#ARG ile de variable tanımlarsınız. Fakat bu variable sadece imaj oluşturulurken yani build aşamasında kullanılır. Imajın oluşturulmuş halinde bu variable bulunmaz. ENV ile imaj oluşturulduktan sonra da imaj içinde olmasını istediğiniz variable tanımlarsınız, ARG ile sadece oluştururken kullanmanız gereken variable tanımlarsınız.
ARG VERSION:1.0
#Imaj içerisinde volume tanımlanamızı sağlayan talimat. Eğer bu volume host sistemde varsa container bunu kullanır. Yoksa yeni volume oluşturur.
VOLUME /myvol
#Bu talimat ile bir containerın çalıştırılabilir bir uygulama gibi ayarlanabilmesini sağlarsınız.
ENTRYPOINT ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]
#Imaj içerisinde volume tanımlanamızı sağlayan talimat. Eğer bu volume host sistemde varsa container bunu kullanır. Yoksa yeni volume oluşturur.
VOLUME /myvol
#Dockerfile'ın komutları işleyeceği shell'in hangisi olduğunu belirtiriz. Linux için varsayılan shell ["/bin/sh", "-c"],Windows için ["cmd", "/S", "/C"]. Bunları SHELL talimatı ile değiştirebiliriz.
SHELL ["powershell", "-command"]
Dockerfile Örnekleri:
FROM ubuntu:18.04
RUN apt-get update -y
RUN apt-get install default-jre -y
WORKDIR /merhaba
COPY /myapp .
CMD ["java", "merhaba"]
FROM ubuntu:18.04
COPY . /app
RUN make /app
CMD python /app/app.py
FROM python:2.7-alpine
WORKDIR /app
ADD requirements.txt /app/requirements.txt
RUN pip install -r requirements.txt
ADD . /app
EXPOSE 80
CMD ["gunicorn","app:app","-b","0.0.0.0:80","--log-file","--access-logfile","-","--workers","4","--keep-alive","o"]
Dockerfile çalıştırma:
docker image build -t besiktas .
docker image ls
#Oluşturulan image'dan container yaratma
docker container run --name alimetinfeyyaz besiktas
#Farklı bir Dockerfile çalıştırma:
docker image build -t besiktas1 -f Dockerfile.test
Oluşturduğumuz imajdan bir container yaratma:
docker run -d -p 8080:8080 --name deneme1 besiktas1
Container’i Hub’a gönderme:
#İlk olarak imajı repo ismiyle tag'lıyoruz.
docker image tag besiktas soner4444/besiktas
#Sonra push edilir.
docker push soner4444/besiktas:latest
#Container'ı inceleme
docker inspect
Container Güvenliği:
#İmaj içerisindeki güvenlik açıklarına bakmak için
docker scout cves javadk
Docker Multi-stage Build:
Bazı yazılım dillerinin çalıştırılması için compile edilmesi lazım örneğin java, c, c# gibi. Fakat eğer biz kodu aşağıdaki ilk Dockerfile’daki gibi ayağa kaldırırsak çalışacaktır fakat bu container’in hem boyutu büyük olacaktır hem de bir müşteriye göndermek istersek imajın içerisinde gereksiz paketler var aynı zamanda kaynak kodları mevcut.
FROM mcr.microsoft.com/java/jdk:8-zulu-alpine
COPY /source /usr/src/uygulama
WORKDIR /usr/src/uygulama
RUN javac uygulama.java
CMD ["java", "uygulama"]
Bu sorunların üstesinden gelmek için ise bir imajın içerisinden compile edilen uygulamayı almak, sadece gerekli paketleri koymak ve yeniden bir container yaratmak gerekir. Aşağıdaki gibi.
docker cp javauygulama:/usr/src/uygulama .
#Dockerfile
FROM mcr.microsoft.com/java/jdk:8-zulu-alpine
COPY /uygulama /uygulama
WORKDIR /uygulama
CMD ["java", "uygulama"]
docker imaje build -t javajre Dockerfile .
Bu işlemler hem zaman hem de uğraştırıcı bir iştir. Bu sorunun üstesinden gelmek için Multi-stage build yöntemi kullanılır.
Multi-stage build, bize bir Dockerfile’da iki işi halletmemizi sağlar aşağıdaki gibi.
FROM mcr.microsoft.com/java/jdk:8-zulu-alpine AS derleyici
COPY /source /usr/src/uygulama
WORKDIR /usr/src/uygulama
RUN javac uygulama.java
FROM mcr.microsoft.com/java/jre:8-zulu-alpine
WORKDIR /usr/src/uygulama
COPY --from=derleyici /usr/src/uygulama .
CMD ["java", "uygulama"]
docker build -t javadeneme .
Build ARG:
Dockerfile’da imaje oluşturmak için değişken kullanmak istersek kullanılır. Örneğin aşağıdaki gibi VERSION adında bir ARG tanımladık bu sayede her Dockerfile çalıştırdığımızda komut satırında ilgili değeri değişken olarak gönderirsek imaj istediğimiz versiyonda oluşturulacaktır.
FROM ubuntu:latest
WORKDIR /gecici
ARG VERSION
ADD https://www.python.org/ftp/python/${VERSION}/Python-${VERSION}.tgz .
CMD ls -la
docker image build -t deneme --build-arg VERSION=3.7.1
Docker Compose:
YAML formatıyla containerları, volumeleri, networkleri vs. her şeyi ayağa kaldırdığımız dosyadır. Örnek docker-compose.yml dosyası.
#5 ana kısım vardır.
version: "3.8"
services:
mysqlsunucu:
image: mysql:latest
restart: always
environment:
MYSQL_DATABASE: wpdatabase
MYSQL_USER: wpuser
MYSQL_PASSWORD: Passwd123@
MYSQL_RANDOM_ROOT_PASSWORD: True
networks:
- wpnet
volumes:
- mysqlvolume:/var/lib/mysql
wpsunucu:
image: wordpress:latest
restart: always
depends_on:
- mysqlsunucu
ports:
- "8080:80"
environment:
WORDPRESS_DB_HOST: mysqlsunucu
WORDPRESS_DB_USER: wpuser
WORDPRESS_DB_PASSWORD: Passwd123@
WORDPRESS_DB_NAME: wpdatabase
networks:
- wpnet
volumes:
- wpvolume:/var/www/html
networks:
wpnet:
driver: bridge
volumes:
mysqlvolume:
wpvolume:
#docker compose çalıştırma
docker compose up -d
#docker compose durdurma
docker compose down
Docker compose durdurulduğunda oluşturduğu tüm containerları networkleri vs. silerek kapanır.
Kaynaklar: