İçeriğe geç

Dockerize Django Uygulamasını Debug Etmek

Merhabalar. Bugün Dockerize edilmiş ve compose ile koşan basit ve nispeten az bağımlılığı bulunan Django uygulamasının nasıl debug edilebileceğinden bahsedeceğim.

$ docker-compose up

komutu kosturuldugunda Docker bulunulan klasördeki docker-compose.yml dosyasına göre servisleri, bağımlılıklarını veya varsa volume gibi nesneleri olusturacak daha sonra ayağa kalkan servislerin stdoutlarını komutu koşturduğumuz terminale bağlayacaktır. Örneğin;

Building with native build. Learn about native build in Compose here: https://docs.docker.com/go/compose-native-build/
postgres_dj is up-to-date
redis_dj is up-to-date
Creating django ... done
Attaching to postgres_dj, redis_dj, django
redis_dj | 1:C 16 May 2021 12:41:54.788 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis_dj | 1:C 16 May 2021 12:41:54.788 # Redis version=6.2.3, bits=64, commit=00000000, modified=0, pid=1, just started
redis_dj | 1:C 16 May 2021 12:41:54.788 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
redis_dj | 1:M 16 May 2021 12:41:54.789 * monotonic clock: POSIX clock_gettime
redis_dj | 1:M 16 May 2021 12:41:54.789 * Running mode=standalone, port=6379.
redis_dj | 1:M 16 May 2021 12:41:54.789 # Server initialized
redis_dj | 1:M 16 May 2021 12:41:54.789 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
redis_dj | 1:M 16 May 2021 12:41:54.790 * Ready to accept connections
postgres_dj | 
postgres_dj | PostgreSQL Database directory appears to contain a database; Skipping initialization
postgres_dj | 
postgres_dj | 2021-05-16 12:41:54.734 UTC [1] LOG:  starting PostgreSQL 13.2 on x86_64-pc-linux-musl, compiled by gcc (Alpine 10.2.1_pre1) 10.2.1 20201203, 64-bit
postgres_dj | 2021-05-16 12:41:54.735 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
postgres_dj | 2021-05-16 12:41:54.735 UTC [1] LOG:  listening on IPv6 address "::", port 5432
postgres_dj | 2021-05-16 12:41:54.742 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
postgres_dj | 2021-05-16 12:41:54.748 UTC [21] LOG:  database system was shut down at 2021-05-16 12:40:33 UTC
postgres_dj | 2021-05-16 12:41:54.752 UTC [1] LOG:  database system is ready to accept connectionslk
django   | Operations to perform:
django   |   Apply all migrations: admin, auth, contenttypes, sessions

Debug.

Şu haliyle debug etmek istediğimiz kısma breakpoint ya da

import pdb; pdb.set_trace()

koymamız, doğrudan Django servis containerına bağlı olmadığmızdan aşağıdaki gibi hata verecek ve çıkış yapacaktır.

django   |   File "/usr/local/lib/python3.9/bdb.py", line 113, in dispatch_line
django   |     if self.quitting: raise BdbQuit
django   | bdb.BdbQuit
django   | HTTP GET / 500 [0.08, 172.22.0.1:33798]

Bu durumu aşmak için 2 farklı yol bulunmakta.

  1. Tüm servisleri ayağa kaldırdıktan sonra, Django uygulamasının bulunduğu containeri durdurup, ayrık olarak yeniden başlatmak. Örnekleyecek olursak;
$ docker-compose up -d
Building with native build. Learn about native build in Compose here: https://docs.docker.com/go/compose-native-build/
Starting postgres_dj ... done
Starting redis_dj    ... done
Starting django      ... done

Detach modda tüm servisleri ayağa kaldırdık.

Daha sonra tekil olarak çalışan Django containerını isme göre arayarak bulduk ve kaldırdık.

$ docker ps -f name=django   
CONTAINER ID   IMAGE           COMMAND                  CREATED          STATUS          PORTS                    NAMES
f0b36007bc7b   app_web   "sh -c 'python manag…"   42 seconds ago   Up 41 seconds   0.0.0.0:8000->8000/tcp   django
$ docker container rm -f django
django

Bu hali ile docker-compose tarafından yönetilecek servisleri listelediğimizde sadece postgres ve redisi görmemiz gerekmekte.

$ docker-compose ps
   Name                  Command               State    Ports  
---------------------------------------------------------------
postgres_dj   docker-entrypoint.sh postgres    Up      5432/tcp
redis_dj      docker-entrypoint.sh redis ...   Up      6379/tcp

Yapmamız gereken son işlem Django servisini tekrar manuel olarak başlatmak. docker-compose’in tekil olarak bir servisi başlatabilme yeteneğini kullanacağız.

$ docker-compose run --rm --service-ports your_django_app_service

Yukarıdaki komutla birlikte Django uygulamanızın tanımlı olduğu servisi docker-compose.yml dosyasında belirtilen ayarlamalar ve portlar ile başlatması gerektiğini, terminal bağlantısı kesildiğinde de sistemden debug container’ını kaldırması gerektiğini söylüyoruz.

Basit bir view yazıp içerisine bir adet breakpoint yerleştirip, 2. terminalden ilgili urle istek attığınızda debug modunun aktifleştirildiğini ve debug edebildiğinizi görebilirsiniz. Afiyet olsun 🙂

System check identified no issues (0 silenced).
May 16, 2021 - 13:29:47
Django version 3.2.2, using settings 'your_app.settings'
Starting ASGI/Channels version 3.0.3 development server at http://0.0.0.0:8000/
Quit the server with CONTROL-C.
> /usr/src/app/your_app/urls.py(10)get()
-> return response.Response({})
(Pdb) self.request
<rest_framework.request.Request: GET '/'>
(Pdb) self.request.query_params
<QueryDict: {}>
(Pdb) 

2. yöntem ise doğrudan docker-compose üzerinden tekil servisi başlatmak.

Aslında yukarıda yaptığımız işlem bu işin biraz uzun yolu.

Servis bağımlıklıkları tanımlanmış, bir docker-compose dosyasında doğrudan ilgili servisi ayağa kaldırmak depends-on bloğunda tanımlanan servisleri de ayağa kaldıracaktır.

Dolayısı ile aşağıdaki komutla web servisini tekil ayağa kaldırarak, yukarıdaki işlemlere gerek duymadan debug yeteneğini elde edebiliriz.

$ docker-compose run --rm --service-ports your_django_app_service
System check identified no issues (0 silenced).
May 16, 2021 - 13:55:28
Django version 3.2.2, using settings 'your_app.settings'
Starting ASGI/Channels version 3.0.3 development server at http://0.0.0.0:8000/
Quit the server with CONTROL-C.
> /usr/src/app/your_app/urls.py(10)get()
-> return response.Response({})
(Pdb) 

Tekrar afiyet olsun 🙂


Sonuç.

Kimse bug yazmaz ama herkes debug yapar. Dockerize edilmiş bir Django uygulamasında nasıl debug yapabileceğimizi artık biliyoruz. Tabi ki bu yöntem benim gibi editor veya ide debug panellerine alışamayan, console debug yapmayı sevenler için.

Eğer VSCode veya PyCharm kullanıyor iseniz ptvsd modulü yardımıyla geliştirme ortamınızı yapılandırarak debug yapabilirsiniz. İki geliştirme ortamı içinde linkleri hemen aşağıya bırakıyorum. Kolay gelsin!

Bu blogta docker ile ilgili daha fazla okumak isterseniz;

Pycharm Debugging.

VS Code debugging.

Tarih:Blog

Tek Yorum

  1. Anonim Anonim

    Selam yazi icin tesekkurler,

    3. bir yontem olarak docker attach ile ayakta duran container’a baglanabiliriz.
    Orn: docker attach container_id

    Attach modunda ipdb’nin calisabilimesi icin docker-compose.yml dosyasinda django’nun calistirildigi container icin sunlari eklemek gerek:

    stdin_open: true
    tty: true

Bir cevap yazın

E-posta hesabınız yayımlanmayacak.

Göster
Gizle