1. sayfa (Toplam 1 sayfa)

Docker Komutları

Gönderilme zamanı: 29 Nis 2023, 08:56
gönderen melihcelenk
Docker kurulumu yapmadan pratik yapmak için:
https://labs.play-with-docker.com/

Docker container'ının varsayılan olarak çalıştırdığı bir uygulama vardır. Bu uygulama sona erdiğinde container kapatılır.
docker version
ile client ve server versiyon bilgilerini öğreniriz.
docker info
ile detaylı client ve server durum bilgilerini öğreniriz. Örneğin çalışan ve durmuş container sayısı.

Her bir adımda --help ile yardım alınabilir.


CONTAINER

docker <Yönetim Birimi> <Komut>
Örnek: docker container run
docker container run hello-world
ile uzaktaki hello-world imajından bir container oluşturup ayağa kaldırırız.
docker container run --name merhaba hello-world
Bu container'a isim vererek ayağa kaldırmak için --name komutunu kullanabiliriz.
docker run -d ubuntu /bin/sh -c "while true; do tail -f /dev/null; done"
şeklinde bir komut ile bir ubuntu container'ı ayağa kaldırıp ayakta kalmasını sağlayabiliriz
docker container rm <container_id>
bir container'ı silebiliriz.
docker container rm -f <container_id>
ile çalışan bir container'ı silebiliriz.
docker container stop <container_id>
ile bir container'ı durdururuz.
docker ps -a
Bütün container'ların listesi
docker container exec -it <container_name> sh
ile bir container'ın içinde shell çalıştırabiliriz.

Buradayken ps yazdığımızda container içinde çalışan uygulamalarımızı görebiliriz. PID'si 1 olan uygulama ilk çalışan uygulamamızdır. Bu uygulamayı
kill 1
komutuyla kapatırsak container'ın da sonlandırıldığını görürüz. (docker ps)

* * *

IMAGE
docker images
veya
docker image ls
ile var olan imajları görürüz.
docker image rm <image_id>
ile imajı silebiliriz.
docker image prune -a
ile var olan tüm imajları silebiliriz
docker image pull nginx
ile nginx imajını çekebiliriz
docker image pull ubuntu:22.04
ile ubuntu'nun 22.04 tag'li (versiyonlu) imajını çekebiliriz
docker image pull gcr.io/google-containers/cadvisor
ile Google Container Registry'den cAdvisor imajını çekebiliriz

https://hub.docker.com/
Docker'ın kendi registry'sine ait imajlarını buradan görebilirsiniz.
Aynı imaja birden fazla tag atanabilir.

Her imaja ait birden fazla tag olabilir. Örneğin postgres için 15.4, 15, latest, 15.4-bookworm gibi tag'lerin hepsi aynı imaja ait tag'lerdir.

Ekran görüntüsü 2023-08-26 221721.png
Ekran görüntüsü 2023-08-26 221721.png (73.04 KiB) 246 kere görüntülendi
docker login
ile Docker Hub'a giriş yaparız.
docker image tag ornek:latest melihcelenk/ornek:latest
ile tag'leyip
docker push melihcelenk/ornek:latest
ile Docker Hub'a etiketlediğimiz imajı göndeririz.
docker commit bircontainer yeniimaj
komutu ile bir bircontainer isimli container'dan yeniimaj isimli bir imaj oluşturabiliriz.
docker save yeniimaj:latest -o yeniimaj.tar
ile yeniimaj'ı bir tar dosyası olarak kaydedebiliriz
docker load -i dizin/yeniimaj.tar
ile tar dosyasını imaj olarak yükleyebiliriz.

Docker registry kurulumu:
https://docs.docker.com/registry/

* * *

VOLUME
docker volume create yeniVolume
ile bir volume oluşturabiliriz.
docker volume inspect yeniVolume
ile bu volume'e ait detayları görebiliriz.
docker container run -it -v yeniVolume:/yeniKlasor alpine sh
ile alphine'den bir imaj oluşturup sh ile bağlanırken yeniVolume isimli volume'ü container içinde yeniKlasor isimli bir klasör oluşturarak bağlamış oluruz.
docker container run -it -v yeniVolume:/baskaKlasor:ro centos sh
ile oluşturduğumuz yeniVolume isimli volume'ü container içinde baskaKlasor isimli bir klasör oluştururarak sadece okunabilir olarak bağlamış oluruz.

* * *
docker cp <container adı>:/kopyalanacak/dizin .
ile bir container içindeki dizinden bulunduğumuz dizine kopyalama yapabiliriz.

* * *
Bir Dockerfile dosyası oluştururuz.
docker build .
ile bulunduğumuz dizinde build alınır. Bu bize bir image id'si verir. Bu image id'sinden bir container oluşturup ayağa kaldırmak için
docker run - p 3000:3000 d2c901271lkja
şeklinde bir komut kullanırız.
docker ps
ile ayakta olan bütün container'ları görürüz.
docker stop <containerAdi>
ile çalışan bir container'ı durdururuz.

Bir image'dan birden fazla çalışan container oluşturulabilir. Bunları farklı ortamlarda kurabiliriz.
docker ps -a
Bütün container'ları gösterir (Ayakta olmayanlar dahil)
docker run -it node
ile bir container'ın içerisine girebiliriz.


* * *

DOCKERFILE

Şimdi daha detaylı bakalım.

Dockerfile komutları:

FROM: Oluşturulacak imaj için hangi imajın kullanılacağını belirtir.
WORKDIR: Kullanılacak komutların dizini belirtilir. cd'den farklı olarak belirtilen dizin yoksa oluşturulur.
COPY: İmaj içine dosya veya klasör kopyalamak için kullanılır.
RUN: Shell'de çalıştırılacak komut belirtilir.
EXPOSE: İmajdan oluşturulacak container'lara hangi portlar üstünden erişilebileceğini belirtir
CMD: Container yaratıldığında varsayılan olarak çalıştırılması istenen komut belirtilir. Örnek: CMD java hello-world
ENTRYPOINT: CMD ile aynı şeyi yapar, ancak container çalıştırılırken override edilemez.
CMD ve ENTRYPOINT Dockerfile'da birlikte kullanıldığında CMD'de yazılan, ENTRYPOINT'te yazılana parametre olarak eklenir.
Örnek:
ENTRYPOINT ["ping"]
CMD["8.8.8.8"]
Uygulama ping 8.8.8.8 komutuyla çalıştırılır.
Her docker imajında bir CMD veya ENTRYPOINT bulunmalıdır.
LABEL: İmaja key/value şeklinde bir metadata eklemek için kullanılır.
HEALTHCHECK: Bir container'ın çalışıp çalışmadığını kontrol etmesi istenilir. Bu ilk process'i izler, ilk process çalışmayı durdurduğunda container da durur.
ADD: COPY'den farklı olarak dosya kaynağı olarak URL de belirtebiliriz. URL olmayan bir tar dosyası kaynak olarak verildiğinde hedefe açılarak kopyalanır.

Daha fazlası için:
https://docs.docker.com/engine/reference/builder/


Basit bir python uygulaması için örnek bir Dockerfile:

Kod: Tümünü seç

FROM ubuntu:18.04
COPY ./app
RUN make /app
CMD python /app/uygulama.py
Bir java uygulaması için örnek bir Dockerfile:

Kod: Tümünü seç

FROM ubuntu:22.04
RUN apt update -y
RUN apt install default-jre -y
WORKDIR /containericindekiklasor
COPY ./src/main/java /containericindekiklasor
# veya COPY ./src/main/java /containericindekiklasor
CMD ["java", "Main.java"]
Bunu daha kolay hâle getirelim. Java Runtime Environment'ın kurulu olduğu resmi bir imaj zaten var. Önerilen, kullanacağınız yazılıma ait resmi imajı bulup onu kullanmaktır. Örneğin Python için Docker Hub'a python, MySQL için Docker Hub'a mysql yazarak bu resmi imajlara (DOCKER OFFICIAL IMAGE yazanlara) ulaşabilirsiniz.

Kod: Tümünü seç

FROM eclipse-temurin
WORKDIR /containericindekiklasor
COPY ./src/main/java /containericindekiklasor
CMD ["java", "Main.java"]
Bu Dockerfile'ı sadece anlamak için kullanalım. Normalde custom bir JRE kullanılması öneriliyor. Nasıl kullanılması gerektiğine eclipse-temurin'in Docker Hub'daki sayfasından ulaşabilirsiniz.
https://hub.docker.com/_/eclipse-temurin

Şimdi de bir Dockerfile ile multi-stage build'ı görelim. Bir imaj oluşturuyoruz ve bu imajda java dosyamızı derleyip diğer imajda bunu kullanıyoruz.

Kod: Tümünü seç

FROM amazoncorretto AS ilkimaj
ENV ORNEK_DEGISKEN="AAA"
WORKDIR /containericindekiklasor
COPY ./src/main/java /containericindekiklasor
RUN javac Main.java

FROM eclipse-temurin
ENV ORNEK_DEGISKEN="BBB"
WORKDIR /containericindekiklasor
COPY --from=ilkimaj /containericindekiklasor .
CMD ["java", "Main"]
Henüz imaj oluşturulurken değişken tanımlamak için ARG komutunu kullanırız. Bunu örneğin bir dosya isminde kullanalım. Main1.java ve Main2.java isimli iki dosyamız olsun. VERSION ortam değişkenine ARG'den gelen değeri atayıp CMD üzerinde kullanabiliriz. CMD runtime'da çalıştığından doğrudan ARG kullanamadığımız için ENV değişkeni oluşturduk. Ama ADD komutuyla doğrudan ARG ile oluşturduğumuz değişkeni kullanabiliriz.

Kod: Tümünü seç

FROM eclipse-temurin
WORKDIR /containericindekiklasor
COPY ./src/main/java /containericindekiklasor
ARG VERSION
ENV VERSION ${VERSION}
CMD java Main${VERSION}.java
Biz Main2'yi çalıştıran bir imaj türetmek istiyoruz.
docker image build -t uygulamaversiyon2 --build-arg VERSION=2 .
ile ARG'nin değerini veririz.

Docker katmanlı bir yapıya sahiptir ve her katman bir kez oluşturulduktan sonra tekrar imaj oluşturulduğunda eğer değişiklik yoksa cache kullanır. Örneğin 7 adımlı bir Dockerfile'ımız olsun. 4. adımda bir değişiklik olduysa ilk 3 katman için cache kullanılır, sonraki adımlar baştan işletilir.

Dockerfile'ın bulunduğu dizinde
docker image build -t uygulama -f Dockerfile .
kullanarak veya dockerfile'ımızın adını Dockerfile olarak girersek
docker image build -t uygulama .
komutu ile "uygulama" olarak tag'lenmiş bir şekilde bu imajı oluşturabiliriz.
docker container run uygulama
ile bu imajdan bir container oluşturup çalıştırabilir
docker container run -it uygulama bash
ile container'ın içine girebiliriz.

Bir node uygulaması için örnek bir Dockerfile:

Kod: Tümünü seç

FROM node   ->   node hazır image'ını çekip kullanacak

WORKDIR /projeklasoru   -> komutların çalışma dizini bu olacak, örneğin aşağıda belirttiğimiz npm install artık bu directory altında çalışacak

COPY . /projeklasoru    -> bulunduğumuz klasörden container içinde /projeklasoru path'ine kopyalayacak

(veya) COPY . ./    -> üstteki yerine bunu da kullanabiliriz, çünkü workdir olarak zaten /projeklasoru olarak belirttik. Ancak üstteki gibi belirtmek daha net ve mantıklı

RUN npm install      ->    uygulamayı yükler

EXPOSE 80 -> sadece dokümantasyon için, container'ın hangi portu üstünden çalıştığını gösterir

CMD ["node", "server.js"]
docker build .
Buradaki "." ile Dockerfile'ın konumunu belirtiriz

Komut sonucunda bize verilen id'yi alalım. Herhangi bir port belirtmeden çalıştıralım ve ne olacağını görelim.
docker run f6c7c8a59ef6525b5f9d7da7296143b9b421b5e25b94d7f4baa643561fb9cc69
EXPOSE 80 yazdığımız hâlde bu porttan erişemediğimizi görürüz. Çünkü bu komut aslında sadece dokümantasyon içindir.
docker ps
docker stop <container name>
ile durduralım.

Bu kez port bilgisi vererek bir container ayağa kaldıralım.

EXPOSE 80 yazdığımız için sağ tarafı 80 olarak, sol tarafı da bilgisayarımızda erişeceğimiz port olarak giriyoruz:
docker run -p 3000:80 f6c7c8a59ef6525b5f9d7da7296143b9b421b5e25b94d7f4baa643561fb9cc69
Bu komut her seferinde bir container oluşturur.
docker ps -a
ile aynı imajdan birden fazla container üretilmiş olduğunu görebiliriz.

Bu kez 3000 portuna bilgisayarımızdan erişebildiğimizi görürüz. 80 portu ise sadece container içinde açıktır.
docker start <container id>
ile var olan bir container'ı çalıştırabiliriz. Böylece her seferinde yeni bir container yaratmayız.

Herhangi bir yerde hiçbir değişiklik yapmadan docker build . komutunu çalıştırırsak çok hızlı sonlanır, aynı image id'yi verir.

Dosyada değişiklik yaparsak ilgili layer'larda değişmeyenler cache'den alınır. Örneğin WORKDIR değişmediği için cache kullanılır, ama dosyalar değiştiği için COPY komutu işletilir. Dockerfile içinde bir layer'da değişiklik yapıldıysa o ve ondan sonraki tüm katmanlar çalıştırılır.
docker run -p 3000:80 -d f6c7c8a5
Log'ları göstermeden bir container oluşturup çalıştırır. (Detached mode)
docker attach <container name>
Bir container için başlatıldığı andan itibarenki log'ları görme (Attached mode)


Bir uygulama yapalım.
FROM nginx:latest
LABEL "com.melihcelenk.vendor"="Melih Çelenk"
ADD https://github.com/melihcelenk/KolaylastiranAraclar .
ENV MUSTERI="Melih Celenk"
ARG TEMA
RUN apt update && \
apt install curl net-tools wget -y
WORKDIR /usr/share/nginx/html
RUN echo "<html> <body> <h1 style='background-color:$TEMA;'> Merhaba $MUSTERI </h1></body> </html>" > index.html;
HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 CMD curl -f http://localhost/ || exit 1
CMD ["nginx", "-g", "daemon off;"]
Bu dockerfile'ı
docker build -t merhaba:kirmizi--build-arg TEMA=Red .
ile imaja dönüştürelim.

Bir de
docker build -t merhaba:sari--build-arg TEMA=Yellow .
ile bir imaj oluşturalım.

Aynı dockerfile ile ARG komutunu kullanarak farklı imajlar yaratmış olduk.
docker container run --name a1c -p 80:80 merhaba:kirmizi
ile merhaba:kirmizi imajından bir container oluşturalım. Ve tarayıcımızda localhost:80 adresini açalım.
docker container run --name a1c -p 8080:80 merhaba:sari
ile merhaba:sari imajından bir container oluşturalım. Ardından tarayıcımızda localhost:8080 adresini açalım.

* * *
Farklı imajlardan iki imaj oluşturduğumuz bir Dockerfile yazalım. Birincisi kodumuzu derlesin, ikincisi çalıştırsın.
FROM mcr.microsoft.com/java/jdk:8-zulu-alpine as derle
WORKDIR /usr/src/uygulama
COPY /source .
RUN javac uygulama.java

FROM mcr.microsoft.com/java/jre:8-zulu-alpine
WORKDIR /uygulama
COPY --from=derle /usr/src/uygulama .
CMD ["java", "uygulama"]
LOGLAR
docker logs <container name>
Basılmış log'ları görme
docker logs --details <container name>
Daha detaylı log'ları görme
docker logs -t <container name>
Basılmış log'ları zaman damgası ile görme
docker logs --until 2023-08-20T13:16:16.981900642Z <container name>
Belirtilen zamana kadar basılmış log'ları görme
docker logs --tail 3 <container name>
Loglardan son 3 satırı görme
docker logs -f <container name>
Basılmış log'ları görme ve görmeye devam etme

* * *

KAYNAKLAR
docker stats
container'ların durumunu görme (memory, cpu vs)
docker container run -d --memory=100m nginx
100 MB memory limitli bir nginx container'ı kaldırır.
docker container run -d --memory=100m --memory-swap=200m nginx
200 MB swap alanı olan 100 MB memory limitli bir nginx container'ı kaldırır.
docker container run -d --cpus="1.5" nginx
İşlemcide kullanabileceği core sayısı 1.5 ile sınırlı bir nginx container'ı kaldırır. Buna --cpus="1.5" ekleyerek
docker container run -d --cpus="1.5" --cpuset-cpus="0,5" nginx
şeklinde yazarsak container'ın işlemcide sadece CPU0 ve CPU5'i kullanmasını sağlayabiliriz.

* * *

ORTAM DEĞİŞKENLERİ
docker container run -it --env DEGISKEN1=ornek --env degisken2=ornek2 ubuntu bash
ile ortam değişkenleri oluştururuz ve içerde
printenv
yazarak oluşturduğumuz değişkenleri görebiliriz.
docker container run -it --env-file /dosya/yolu/env_dosyasi ubuntu bash
ile ortam değişkenlerini oluşturduğumuz dosya üzerinden atayabiliriz.

* * *

NETWORK
docker network ls
ile network objelerini listeleriz.
docker network inspect <objeadı>
ile bridge network objesinin bütün özelliklerini listeleriz. Obje bir container olabilir.
docker network inspect bridge
ile varsayılan olarak oluşturulmuş bridge network'ünün özelliklerini listeleriz.
docker container run -it --net host alpine sh
ile alpine imajından bir container'ı host modunda oluşturup içine gireriz
docker network create yeniKopru
ile yeni bir network objesi oluştururuz.
docker container run --name ornek1 -dit --net yeniKopru alpine sh
docker container run --name ornek2 -dit --net yeniKopru alpine sh
ile yeniKopru network'üne bağlı iki farklı container oluşturursak
docker attach ornek1
ile terminale bağlanıp
ping ornek2
yazdığımızda ornek2'ye ismi üzerinden ping atabiliriz.
docker attach websunucu
docker network create --driver=bridge --subnet=10.10.0.0/16 --ip-range 10.10.10.0/24 --gateway 10.10.10.10 yeniKopru2
ile istediğimiz subnet ve ip aralığında, 10.10.10.10 gateway'li bir network objesi yaratabiliriz.
docker network connect yeniKopru2 ornek1
ile çalışan ornek1 container'ını oluşturduğumuz yeniKopru2 network'üne bağlayabiliyoruz.
docker network disconnect yeniKopru2 ornek1
ile network bağlantısını kesebiliriz.

DOCKER-COMPOSE
docker-compose up
komutunu docker-compose.yml dosyamızın olduğu dizinde girerek bu compose dosyasını çalıştırabiliriz.
docker-compose down
ile compose'da ayağa kaldırdığımız şeyleri indirebiliriz.
docker-compose build
docker-compose içinde kullanılan build komutunu çalıştırıp imajı oluşturur

DOCKER SWARM
TCP 2377 (Cluster yönetimi)
TCP ve UDP 7946(Node'lar arası iletişim)
UDP 4789 (Overlay Network için)
portları açık olmalı

Raft algoritmasının düzgün çalışabilmesi ve lider seçiminin sorunsuz olabilmesi için tek sayıda manager node seçilmiş olması gerekmektedir.
docker swarm init --advertise-addr 192.168.0.18
192.168.0.18 üzerinden swarm modunu devreye alıp komutun yazıldğı node'u amnager olarak atar.
docker info
ile swarm'un aktif olup olmadığına bakabiliriz. (Swarm: active)
docker-swarm join-token manager
Bu swarm'a bir manager eklemek için gereken komutu gösterir

Başka bir makineden yukarıda aldığımız aşağıdaki komutu çalıştırarak bunu bir manager olarak ekleriz:
docker swarm join --token SWMTKN-1-0b97yxi3odqst2v2g624ebtelf3tse1l9xzoicu113yj49sqsl-5impyvnx6r5zybvekag8whciv 192.168.0.18:2377
Ardından
docker-swarm join-token worker
yazarak swarm'a bir worker eklemek için gereken komutu alırız.

Bu komut da bize aynı şekilde bir join komutu verir ve başka bir makinede aşağıdaki gibi bir komut gireriz.
docker swarm join --token SWMTKN-1-0b97yxi3odqst2v2g624ebtelf3tse1l9xzoicu113yj49sqsl-0klp2hep8ub28023rsfo9a006 192.168.0.18:2377
Bir swarm'a ait node'ları listelemek için herhangi bir manager node'da
docker node ls
komutunu kullanırız.
docker service create --name ornek --replicas=5 -p 8080:80 nginx
ile ornek isimli servisten 5 container oluşturup worker node'lara dağıtır.
docker service ps ornek
ile container'ların hangi node'larda çalıştığını görebiliriz.
dockerservicepsornek.png
dockerservicepsornek.png (11.19 KiB) 189 kere görüntülendi
Herhangi bir node devre dışı kaldığında yine 5 container çalışacak şekilde container'lar node'lara aşağıdaki gibi dağıtılacaktır.
dockerservicepsornek2.png
dockerservicepsornek2.png (15.93 KiB) 188 kere görüntülendi
docker service inspect ornek
ornek servisinin detaylarını gösterir.
docker service logs ornek
ile servis altında çalışan container'ların loglarını görürüz.
docker service scale ornek=3
ile çalışan task sayısını 3 yapabiliriz.
docker service rm ornek
ile ornek servisini silebiliriz.
docker network -d overlay orneknetwork
ile orneknetwork isminde bir overlay network tanımlayabiliriz. Buna bütün swarm üzerinden erişilebilir.
docker service create --name ornekservice --network orneknetwork -p 8080:80 --replicas=5 ornekimaj:versiyon1
ile ilgili parametrelere sahip bir servis oluşturabiliriz.
docker service update --detach --update-delay 5s --update-parallelism 2 --image ornekimaj:versiyon2
aynı anda 2 task update edip her 2 task update'i arasında 5 saniye beklemesini sağlayabiliriz
docker service rollback --detach ornekservice
ile bir sorun çıktığında yaptığımız update'i geri alabiliriz

Secret
Swarm'un aktif olduğu bir ortamda
docker secret create ornekdegisken ./ornekdegisken.txt
ile dosya vererek veya
"Bu bir degisken." | docker secret create ornekdegisken -
şeklinde doğrudan secret oluşturabiliriz.
docker service create -d --name ornekservice --secret ornekdegisken ornekimaj
ile oluşturduğumuz değişkeni bir servise atayabiliriz.

Container içine girip /run/secrets klasöründe ornekdegisken.txt'yi içine değişken değeri yazılmış şekilde görebilirsiniz.
docker service update --secret-rm ornekdegisken --secret -add yeniornekdegisken ornekimaj
ile secret güncelleyebiliriz.

Stack
docker stack deploy -c /dizin/docker-compose.yml ornekstack
ile stack oluşturabiliriz.
docker stack services ornekstack
ile ornekstack altında oluşturulan servisleri görürüz.