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.
- 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!
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