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.
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
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.
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.
- [Django]-Django ModelForm โ name 'Article' is not defined
- [Django]-Django official tutorial for the absolute beginner, absolutely failed!
- [Django]-How to solve the strptime() caused naive datetime RuntimeWarning?
- [Django]-Getting 400's from aws ELB hostcheck to work with django ALLOWED_HOSTS in aws ECS under awsvpc networking mode?
- [Django]-Django WSGI deployment. cannot import name 'SimpleCookie'
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.
- [Django]-Django and Session Status Messages
- [Django]-How to rewrite base url in django to add logged in username in the url of all pages instead of app name?
- [Django]-Fresh python 3.7 / django 2.2.1 installation not recognising that mysqlclient is installed
- [Django]-Django templates loops
- [Django]-Django charfield with default empty string is required in admin
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/