How to update code in a docker container? How to update code in a docker container? django django

How to update code in a docker container?


In my experience Docker serves two purposes:

  1. To be able to develop code in a containerized environment. This is very useful as I am now able to get new developers on my team ready to work in about 5 mins Previously, this could have taken anywhere from an hour to several hours for misc issues, especially on older projects.
  2. To be able to package an application in a containerized environment. This is also a great time saver as the only requirement for the environment is to have Docker installed.

When you are developing your code you should mount the source/volume so that your changes are always reflected inside the container. When you want to package an app for deployment you should COPY the source into the container and package it appropriately.

Here is a docker-compose file I use to (1) build an image to develop against, (2) develop my code, and (3) ship it (I'm using spring boot):

version: '3.7'services:  dev:    image: '${MVN_BUILDER}'    container_name: '${CONTAINER_NAME}'    ports:      - '8080:8080'    volumes:      - './src:/build/src'      - './db:/build/db'      - './target:/build/target'      - './logs:/build/logs'    command: 'mvn spring-boot:run -Drun.jvmArguments="-Xmx512m" -Dmaven.test.skip=true'  deploy:    build:      context: .      dockerfile: Dockerfile-Deploy      args:        MVN_BUILDER: '${MVN_BUILDER}'    image: '${DEPLOYMENT_IMAGE}'    container_name: '${CONTAINER_NAME}'    ports:      - '8080:8080'  maven:    build:      context: .      dockerfile: Dockerfile    image: '${MVN_BUILDER}'    container_name: '${CONTAINER_NAME}'
  1. I would run docker-compose build maven to build my base image. This is needed so that when I run my code in a container all the dependencies are installed in the image. The Dockerfile for this essentially copies to pom.xml into the image and downloads the dependencies needed for the app. Note this would need to be performed anytime dependencies change. Here is the Dockerfile to build that image that is referenced in the maven service:
### BUILD a maven builder. This will contain all mvn dependencies and act as an abstraction for all mvn goalsFROM maven:3.5.4-jdk-8-alpine as builder#Copy Custom Maven settings#COPY settings.xml /root/.m2/# create app folder for sourcesRUN mkdir -p /buildRUN mkdir -p /build/logs# The WORKDIR instruction sets the working directory for any RUN, CMD, ENTRYPOINT, COPY and ADD instructions that follow it in the Dockerfile.WORKDIR /buildCOPY pom.xml /build#Download all required dependencies into one layerRUN mvn -B dependency:go-offline dependency:resolve-pluginsRUN mvn clean install
  1. Next, I would run docker-compose up dev to start my dev service and begin to develop my application. This service mounts my code into the container and uses Maven to start a spring boot application. Anytime I change the code spring boot restarts the server and my changes are reflected.

  2. Finally, once I am happy with my application I build an image that has my application packaged for deployment using docker-compose build deploy. I use a two-stage build process to first copy the source into a container and package it for deployment as a Jar then that Jar is put into the 2nd stage where I can simply run java -jar build/app.jar (in the container) to start my application and the first stage is removed. That's It! Now you can deploy this latest image anywhere Docker is installed.

Here is what that last Dockerfile (Dockerfile-Deploy) looks like:

ARG MVN_BUILDER### Stage 1 - BUILD imageFROM $MVN_BUILDER as builderCOPY src /build/srcRUN mvn clean package -PLOCAL### Stage 2 - Deploy JarFROM openjdk:8RUN mkdir -p /buildCOPY --from=builder /build/target/*.jar /build/app.jarEXPOSE 8080  ENTRYPOINT ["java","-jar","build/app.jar"] 

Here the .env file in the same directory as the docker-compose file. I use it to abstract image/container names and simply bump up the version number in one place when a new image is needed.

MVN_BUILDER=some/maven/builder:0.1DEPLOYMENT_IMAGE=some/deployment/spring:0.1CONTAINER_NAME=spring-containerCONTAINER_NAME_DEBUG=spring-container-debug


I think it's too late to answer your question, however, it might be beneficial for others who reach out.

The tutorial you mentioned is a bit tricky to use for the first-timers, so, I change the structure a little bit. I assume that you have a docker registry account (like Dockerhub) for the purpose of publishing the images to. This is required if you want to access the image on a remote host (you can copy the actual image file but is not recommended).

creating a project

Assume that you are going to create a website with Django and dockerize it, first, you do:

django-admin startproject samplesite

It creates a directory samplesite that includes the following (I added requirements.txt):

db.sqlite3  manage.py  requirements.txt  samplesite

adding Dockerfile and docker-compose.yml

For the Dockerfile, as you can see, nothing is changed compared to the Dockerfile.

FROM python:3ENV PYTHONUNBUFFERED 1RUN mkdir /codeWORKDIR /codeCOPY requirements.txt /code/RUN pip install -r requirements.txtCOPY . /code/

However for the docker-compose.yml:

version: '3'services:  db:    image: postgres  web:    build: .    image: yourUserNameOnDockerHub/mywebsite:0.1  # this line is added    command: python manage.py runserver 0.0.0.0:8000    #volumes:    #  - .:/code    ports:      - "8000:8000"    depends_on:      - db

docker-compose.yml is also almost identical to the one mentioned in the tutorial, with volume commented and one line added image: mywebsite:0.1. This line allows us to track the built image and deploy it whenever we want. The volume mounting is not related to the code you write and was put there to take out the dynamic content that is changed by Django (sqlite, uploaded files, etc.).

build and run

If you run docker-compose up the first time everything works fine, however, because of the new line added, when you change the code after the first time, the changes will not reflect in the container that runs. This is because upon each docker-compose up, compose will look for mywebsite:0.1 (that already exists) and does not build a new image and creates a container based on the old one. As we need that image name and tag to publish/deploy our image, we need to instead use:

docker-compose up --build

It will re-build an image with the changes reflected. Every time you make some changes, run it and a new fresh image is created that can be seen with (note that although the name and tag remain unchanged, change in image id shows that this is a new image):

$ docker imagesREPOSITORY                                   TAG                 IMAGE ID            CREATED             SIZEyourUserNameOnDockerHub/mywebsite            0.1                 033c9d2bfac0        7 seconds ago       974MB

publishing and deployment

If you have set up an account on Dockerhub (or any other registry) you can publish the image for later use or deployment on a remote server:

docker push yourUserNameOnDockerHub/mywebsite:01 

If you want to deploy it on a remote host and want to use docker-compose again, Just change the docker-compose.yml to:

version: '3'services:  db:    image: postgres  web:    image: yourUserNameOnDockerHub/mywebsite:0.1     command: python manage.py runserver 0.0.0.0:8000    #volumes:    #  - .:/code    ports:      - "8000:8000"    depends_on:      - db

Note that the build: . line is removed (as we are going to run it only). When developing locally, whenever you run docker-compose up --build a new image will be created and tagged and a container based on that will run in the compose stack. If you thought that you are happy with the changes, you follow the publishing step to make it live on the server.


When you want to update an image, lets say due to your application code changes, you use COPY during your image-build, so in the Dockerfile you do something like

COPY /you/code/on/the/host /var/www

Also see my answer about "volumes" and image-building https://stackoverflow.com/a/39314602/3625317 to clarify why your code is missing in the build