[Django]-Have different base image for an application in docker

2๐Ÿ‘

โœ…

No, you can not create your image like this, the only image that will treat as the base image in the Dockerfile you posted will be the last FROM gunicor. what you need is multi-stage builds but before that, I will clear some concept about such Dockerfile.

A parent image is the image that your image is based on. It refers to
the contents of the FROM directive in the Dockerfile. Each subsequent
declaration in the Dockerfile modifies this parent image. Most
Dockerfiles start from a parent image, rather than a base image.
However, the terms are sometimes used interchangeably.

But in your case, I will not recommend putting everything in one Dockerfile. It will kill the purpose of Containerization.

Rule of Thumb

One process per container

Each container should have only one concern

Decoupling applications into multiple containers makes it much easier to scale horizontally and reuse containers. For instance, a web application stack might consist of three separate containers, each with its own unique image, to manage the web application, database, and an in-memory cache in a decoupled manner.

dockerfile_best-practices

Apart from Database, You can use multi-stage builds

If you use Docker 17.05 or higher, you can use multi-stage builds to
drastically reduce the size of your final image, without the need to
jump through hoops to reduce the number of intermediate layers or
remove intermediate files during the build.

Images being built by the final stage only, you can most of the time
benefit both the build cache and minimize images layers.

Your build stage may contain several layers, ordered from the less
frequently changed to the more frequently changed for example:

  • Install tools you need to build your application

  • Install or update library dependencies

  • Generate your application

use-multi-stage-builds

enter image description here

With the multi-stage build, The Dockerfile can contain multiple FROM lines and each stage starts with a new FROM line and a fresh context. You can copy artifacts from stage to stage and the artifacts not copied over are discarded. This allows to keep the final image smaller and only include the relevant artifacts.

๐Ÿ‘คAdiii

3๐Ÿ‘

You can use multiple FROM in the same Dockerfile, provided you are doing a multi-stage build

One part of the Dockerfile would build an intermediate image used by another.

But that is generally use to cleanly separate the parents used for building your final program, from the parents needed to execute your final program.

๐Ÿ‘คVonC

1๐Ÿ‘

Is it possible? Yes, Technically multiple base images (FROM XXXX) can appear in single docker file. But it is not for what you are trying to do. They are used for multi-stage builds. You can read more about it here.

The answer to your question is that, if you want to achieve this type of docker image, you should use one base image and install everything else in it with RUN commands like this.

FROM ubuntu

RUN apt install postgresql # install postgresql

...

Obviously it is not that simple. base ubuntu image is very minimal you have to install all dependencies and tools needed to install python, postgres and gunicorn yourself with RUN commands. For example, if you need to download python source code using

RUN wget https://www.python.org/ftp/python/3.7.4/Python-3.7.4.tgz 

wget (most probably) is not pre installed in ubuntu image. You have to install it yourself.

Should I do it? I think you are going against the whole idea of dockerization of apps. Which is not to build a monolithic giant image containing all the services, but to divide services in separate containers. (Generally there should be one service per container) and then make these containers talk to each other with docker networking tools. That is you should use one container for postgres one for nginx and one for gunicorn, run them separately and connect them via network.There is an awesome tool, docker-compose, comes with docker to automate this kind of multi-container setup. You should really use it. For more practical example about it, please read this good article.

๐Ÿ‘คNafees Anwar

1๐Ÿ‘

You can use official docker image for django https://hub.docker.com/_/django/ .
It is well documented and explained its dockerfile.

If you wants to use different base image then you must go with docker-compose.
Your docker-compose.yml will look like

    version: '3'

    services:
    web:
        restart: always
        build: ./web
        expose:
        - "8000"
        links:
        - postgres:postgres
        - redis:redis
        volumes:
        - web-django:/usr/src/app
        - web-static:/usr/src/app/static
        env_file: .env
        environment:
        DEBUG: 'true'
        command: /usr/local/bin/gunicorn docker_django.wsgi:application -w 2 -b :8000

    nginx:
        restart: always
        build: ./nginx/
        ports:
        - "80:80"
        volumes:
        - web-static:/www/static
        links:
        - web:web

    postgres:
        restart: always
        image: postgres:latest
        ports:
        - "5432:5432"
        volumes:
        - pgdata:/var/lib/postgresql/data/

    redis:
        restart: always
        image: redis:latest
        ports:
        - "6379:6379"
        volumes:
        - redisdata:/data

    volumes:
    web-django:
    web-static:
    pgdata:
    redisdata:

follow this blog for details https://realpython.com/django-development-with-docker-compose-and-machine/

๐Ÿ‘คSaleem Ali

Leave a comment