Dockerizing Django projects

Dockerizing Django projects

Pros and Cons of the different ways there are to turn a Django project into a Docker container.

943620c3bc4056a40ce132690f1d9ac1?s=128

Roberto Rosario

April 15, 2016
Tweet

Transcript

  1. Dockerizing Django projects Roberto Rosario robertorosario.com

  2. Who am I? robertorosario.com me@robertorosario.com Roberto Rosario

  3. None
  4. What is Docker?

  5. Docker provides an integrated technology suite that enables development and

    IT operations teams to build, ship, and run distributed applications anywhere.
  6. In human now.

  7. Containers.

  8. Lightweight virtualization. ie: No video hardware emulation.

  9. Some devops now hate me.

  10. Deploy everywhere.

  11. Easy scalability.

  12. Even auto scaling.

  13. Deploying Django: Old school.

  14. None
  15. None
  16. None
  17. None
  18. None
  19. None
  20. Deployed! Congratulations!

  21. Your users have now quadrupled!

  22. None
  23. None
  24. Server are old, let’s go virtual!

  25. None
  26. None
  27. None
  28. Different technology, same problem.

  29. None
  30. None
  31. None
  32. None
  33. Django and Docker?

  34. Configuration files.

  35. First steps.

  36. None
  37. None
  38. Classes Instances

  39. More devops hate me now.

  40. None
  41. Dockerfile

  42. An entire OS for just a part of the Django

    project?
  43. Not to worry.

  44. None
  45. None
  46. Your Django project

  47. Your Django project

  48. Your Django project image Your Django project

  49. Base image = Base class Your image = Subclass

  50. Pretty much every devops hate me at this point.

  51. One size doesn’t fit all.

  52. Monolithic

  53. App Workers Web server

  54. docker run --name postgres -e POSTGRES_DB=mayan -e POSTGRES_USER=mayan -e POSTGRES_PASSWORD=mysecretpassword

    -v /var/lib/postgresql/data -d postgres docker run --name redis -d redis docker run --name mayan-edms -p 80:80 --link postgres:postgres --link redis:redis -e POSTGRES_DB=mayan -e POSTGRES_USER=mayan -e POSTGRES_PASSWORD=mysecretpassword -v /usr/local/lib/python2.7/dist- packages/mayan/media -d mayanedms/monolithic
  55. • Single download • Low entry barrier • Easiest to

    maintain • Big size download • Not good for scaling • Same VM/Server problem
  56. Split

  57. App Workers Web server

  58. Split ~ Frontend + Backend

  59. • Scale individually • Smaller download • Best approach for

    production • Harder to setup • Need documentation • Several DockerFiles
  60. Mixed

  61. Role Frontend Backend

  62. None
  63. • Single download • Can reuse configuration file templates •

    Single core repo • Bigger size download
  64. Lean

  65. Lean = Split without any 3rd party

  66. App Workers Web server

  67. • Smallest download • Hardest to configure • Might not

    scale best • Might violate port export concept
  68. Django + uWSGI NGINX

  69. Django + uWSGI NGINX TCP Port uwsgi_pass 127.0.0.1:3031; socket =

    127.0.0.1:3031
  70. Django + uWSGI NGINX socket = /tmp/uwsgi.sock uwsgi_pass unix:///tmp/uwsgi.sock; ?

  71. Django + uWSGI NGINX socket = /tmp/uwsgi.sock uwsgi_pass unix:///tmp/uwsgi.sock; Volume?

  72. • Need to include NGINX config

  73. $ docker run --name some-nginx -v /some/nginx.conf:/etc/nginx/nginx.conf:ro -d nginx

  74. environment: - NGINX_HOST=foobar.com - NGINX_PORT=80 command: /bin/bash -c "envsubst <

    /etc/nginx/conf.d/mysite.template > /etc/nginx/conf. d/default.conf && nginx -g 'daemon off;'"
  75. Last approach

  76. Kitchen sink

  77. App Workers Database Web server Broker

  78. • Single download • Lowest entry barrier • Biggest size

    download • Terrible for scaling • Same VM/Server problem • Support 3rd party software
  79. None
  80. Educational purposes only

  81. Don’t use in production

  82. EVER!

  83. Kitchen sink will freeze your servers

  84. Devops don’t like frozen servers

  85. None
  86. Don’t turn your devops into Gordon Ramsay

  87. Post init actions

  88. migrate & collectstatic

  89. None
  90. None
  91. None
  92. None
  93. Service synchronization

  94. $ docker run --name postgres -e POSTGRES_DB=mayan -e POSTGRES_USER=mayan -e

    POSTGRES_PASSWORD=mysecretpassword -v /var/lib/postgresql/data -d postgres $ docker run --name redis -d redis $ docker run --name mayan-edms -p 80:80 --link postgres:postgres --link redis:redis -e POSTGRES_DB=mayan -e POSTGRES_USER=mayan -e POSTGRES_PASSWORD=mysecretpassword -v /usr/local/lib/python2.7/dist- packages/mayan/media -d mayanedms/monolithic
  95. Database connection error.

  96. None
  97. $ docker run --name postgres -e POSTGRES_DB=mayan -e POSTGRES_USER=mayan -e

    POSTGRES_PASSWORD=mysecretpassword -v /var/lib/postgresql/data -d postgres $ docker run --name redis -d redis $ docker run --name mayan-edms -p 80:80 --link postgres:postgres --link redis:redis -e POSTGRES_DB=mayan -e POSTGRES_USER=mayan -e POSTGRES_PASSWORD=mysecretpassword -v /usr/local/lib/python2.7/dist- packages/mayan/media -d mayanedms/monolithic
  98. $ docker run --name postgres -e POSTGRES_DB=mayan -e POSTGRES_USER=mayan -e

    POSTGRES_PASSWORD=mysecretpassword -v /var/lib/postgresql/data -d postgres $ docker run --name redis -d redis $ docker run --name mayan-edms -p 80:80 --link postgres:postgres --link redis:redis -e POSTGRES_DB=mayan -e POSTGRES_USER=mayan -e POSTGRES_PASSWORD=mysecretpassword -v /usr/local/lib/python2.7/dist- packages/mayan/media -d mayanedms/monolithic until nc -z $POSTGRES_PORT_5432_TCP_ADDR $POSTGRES_PORT_5432_TCP_PORT; do echo "$(date) - waiting for postgres..." sleep 1 done
  99. Service synchronization doesn’t belong in configuration files.

  100. until nc -z $POSTGRES_PORT_5432_TCP_ADDR $POSTGRES_PORT_5432_TCP_PORT; do echo "$(date) - waiting

    for postgres..." sleep 1 done until nc -z $RABBITMQ_PORT_5672_TCP_ADDR $RABBITMQ_PORT_5672_TCP_PORT; do echo "$(date) - waiting for rabbitmq..." sleep 1 done
  101. More problems.

  102. • Not foolproof • Mute services • nc is not

    universal • API URL paths?
  103. Solutions?

  104. None
  105. $ docker run -d --name mycontainer some-image-or-other $ docker run

    --link mycontainer:mycontainer aanand/wait waiting for TCP connection to 172.17.0.105:5432......ok
  106. Interesting, but...

  107. None
  108. An entire container to run nc.

  109. Cool solution, wrong problem.

  110. None
  111. None
  112. It’s the container manager’s responsibility.

  113. None
  114. None
  115. Kubernetes approach

  116. None
  117. Port, path, initial delay & timeout!

  118. None
  119. None
  120. Docker upstream native approach needed

  121. None
  122. None
  123. Templating

  124. Docker images are static. Less reusable.

  125. None
  126. Docker containers are configured with environment variables.

  127. None
  128. uWSGI support environment variables. NGINX doesn’t.

  129. Docker upstream native approach needed

  130. None
  131. None
  132. “Thank you for using Docker” “But your fix is in

    another repository”
  133. None
  134. Options?

  135. None
  136. And then there is genius

  137. None
  138. None
  139. Bonus

  140. None
  141. Can help with logs too

  142. None
  143. Demo time

  144. Lessons learned?

  145. None
  146. None
  147. None
  148. None
  149. None
  150. Thank you!