How to let docker container install latest dependencies version - docker

I have a docker image that is build from Dockerfile. It has pip installation inside with custom library. Now the image is used in docker-compose service.
requirements.txt
example-library-1
example-library-2
Dockerfile
FROM python:3.7-alpine
WORKDIR /code
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
COPY . .
CMD ["flask", "run"]
docker build -t example_user/example_image .
docker-compose.yml
version: "3.9"
services:
web:
image: example_user/example_image
ports:
- "8000:5000"
When I have a new version for example-library-1, how do I update the docker-compose service to use the new library?
I had tried docker-compose up -d and docker-compose restart web but it does not check for new library version.
Is there a way to do this without docker-compose down and docker-compose up -d?

You can add a build key to the compose file.
services:
web:
image: example_user/example_image
build:
context: path/to/context
dockerfile: path/to/Dockerfile
Then you run compose with the build flag.
docker compose up --build
That said, compose does not have something like rolling updates. You need to stop to compose service and do up with the build flag in order to rebuild.
If you need to rolling updates, you need to use a different operator, like swarm or Kubernetes.

The docker-compose build flag is a good idea.
After that I recommend to use --no-cache flag because the docker buildkit may cache some layer.
Check here the documentation.
Don't forget to check the DOCKER_BUILDKIT environment variable too.

Related

docker build command doesn't refresh my source files

I made a typo in my source code and I noticed it after i run docker-compose up in my cli. I tried rebuilding the project but didn't change my index.js cached code.
This is my Dockerfile
FROM node:alpine
WORKDIR '/app'
COPY package.json .
RUN npm install
COPY . .
CMD [ "npm","start" ]
docker-compose.yml
version: '3'
services:
redis-server:
image: 'redis'
node-app:
build: .
ports:
- "4001:8081"
I recreated the image
$ sudo docker build -t phillalexakis/visits:latest .
and run
docker-composer up
It didn't change the source code at all, what have I completely missed? (I'm new with docker)
Docker-compose is looking for an image named [folder_name]_node-app, but the image you've built is tagged phillalexakis/visits.
Change your node-app service in docker-compose.yml file :
node-app:
build: .
image: node-app
And use docker-compose to build the images:
docker-compose build or docker-compose up --build

What is the purpose of building a docker image inside a compose file?

I was reading Quickstart: Compose and Django when I came across "defining a build in a compose file". Well I've seen it before but what I'm curious about here is what's the purpose of it? I just can't get it.
Why we just don't build the image once (or update it whenever we want) and use it multiple times in different docker-compose files?
Here is the Dockerfile:
FROM python:3
ENV PYTHONUNBUFFERED 1
RUN mkdir /code
WORKDIR /code
COPY requirements.txt /code/
RUN pip install -r requirements.txt
COPY . /code/
And here is docker-compose.yml:
version: '3'
web:
# <<<<
# Why not building the image and using it here like "image: my/django"?
# <<<<
build: .
command: python manage.py runserver 0.0.0.0:8000
volumes:
- .:/code
ports:
- "8000:8000"
You might say: "well, do as you wish!" Why I'm asking is because I think there might be some benefits that I'm not aware of.
PS:
I mostly use Docker for bringing up some services (DNS, Monitoring, etc. Never used it for
development).
I have already read this What is the difference between `docker-compose build` and `docker build`?
There's no technical difference between docker build an image and specifying an image: in the docker-compose.yml file, and specifying the build: metadata directly in the docker-compose.yml.
The benefits to using docker-compose build to build images are more or less the same as using docker-compose up to run containers. If you have a complex set of -f path/Dockerfile --build-arg ... options, you can write those out in the build: block and not have to write them repeatedly. If you have multiple custom images that need to be built then docker-compose build can build them all in one shot.
In practice you'll frequently be iterating on your containers, which means you will need to run local unit tests, then rebuild images, then relaunch containers. Being able to drive the Docker end of this via docker-compose down; docker-compose up --build will be easier will be more convenient than remembering all of the individual docker build commands you need to run.
The one place where this doesn't work well is if you have a custom base image. So if you have a my/base image, and your application image is built FROM my/base, you need to explicitly run
docker build -t my/base base
docker build -t my/app app
docker run ... my/app
Compose doesn't help with the multi-level docker-build sequence; you'll have to explicitly docker build the base image.

docker-compose failed to run the container

I am using this docker-compose.yml file to build an image.
Problem is when I don't use the docker-compose.yml instead use the usual docker build command, it works fine. But when I use the same Dockerfile to build the using the docker-compose it doesn't work.
This is my Dockerfile
# Use an official node runtime as a parent image
FROM node:8
WORKDIR /app/
# Install dependencies
COPY package.json /app/
RUN npm install
# Add rest of the client code
COPY . /app/
EXPOSE 3000
CMD npm start
and this is my docker-compose.yml
version: "3.2"
services:
frontend:
build: ./my-app
ports:
- 80:3000
command: npm start
Container exited right after it creates when using the docker-compose
Can someone please help me?
[Update]
This is the error I am getting

multi-stage build in docker compose?

How can I specify multi-stage build with in a docker-compose.yml?
For each variant (e.g. dev, prod...) I have a multi-stage build with 2 docker files:
dev: Dockerfile.base + Dockerfile.dev
or prod: Dockerfile.base + Dockerfile.prod
File Dockerfile.base (common for all variants):
FROM python:3.6
RUN apt-get update && apt-get upgrade -y
RUN pip install pipenv pip
COPY Pipfile ./
# some more common configuration...
File Dockerfile.dev:
FROM flaskapp:base
RUN pipenv install --system --skip-lock --dev
ENV FLASK_ENV development
ENV FLASK_DEBUG 1
File Dockerfile.prod:
FROM flaskapp:base
RUN pipenv install --system --skip-lock
ENV FLASK_ENV production
Without docker-compose, I can build as:
# Building dev
docker build --tag flaskapp:base -f Dockerfile.base .
docker build --tag flaskapp:dev -f Dockerfile.dev .
# or building prod
docker build --tag flaskapp:base -f Dockerfile.base .
docker build --tag flaskapp:dev -f Dockerfile.dev .
According to the compose-file doc, I can specify a Dockerfile to build.
# docker-compose.yml
version: '3'
services:
webapp:
build:
context: ./dir
dockerfile: Dockerfile-alternate
But how can I specify 2 Dockerfiles in docker-compose.yml (for multi-stage build)?
As mentioned in the comments, a multi-stage build involves a single Dockerfile to perform multiple stages. What you have is a common base image.
You could convert these to a non-traditional multi-stage build with a syntax like (I say non-traditional because you do not perform any copying between the layers and instead use just the from line to pick from a prior stage):
FROM python:3.6 as base
RUN apt-get update && apt-get upgrade -y
RUN pip install pipenv pip
COPY Pipfile ./
# some more common configuration...
FROM base as dev
RUN pipenv install --system --skip-lock --dev
ENV FLASK_ENV development
ENV FLASK_DEBUG 1
FROM base as prod
RUN pipenv install --system --skip-lock
ENV FLASK_ENV production
Then you can build one stage or another using the --target syntax to build, or a compose file like:
# docker-compose.yml
version: '3.4'
services:
webapp:
build:
context: ./dir
dockerfile: Dockerfile
target: prod
The biggest downside is the current build engine will go through every stage until it reaches the target. Build caching can mean that's only a sub-second process. And BuildKit which is coming out of experimental in 18.09 and will need upstream support from docker-compose will be more intelligent about only running the needed commands to get your desired target built.
All that said, I believe this is trying to fit a square peg in a round hole. The docker-compose developer is encouraging users to move away from doing the build within the compose file itself since it's not supported in swarm mode. Instead, the recommended solution is to perform builds with a CI/CD build server, and push those images to a registry. Then you can run the same compose file with docker-compose or docker stack deploy or even some k8s equivalents, without needing to redesign your workflow.
you can use as well concating of docker-compose files, with including both dockerfile pointing to your existing dockerfiles and run docker-compose -f docker-compose.yml -f docker-compose.prod.yml build

create docker-compose file from Dockerfile

I have this simple Dockerfile:
FROM node:boron
# Create app directory
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
# Install app dependencies
COPY package.json /usr/src/app/
RUN npm install
# Bundle app source
COPY . /usr/src/app
EXPOSE 8080
CMD [ "npm", "start" ]
I would like to use docker-compose so that I can simply say docker-compose up or docker-compose down.
I am struggling to find a simple docker-compose example of how I would use docker-compose, all I can find are examples like this which cover more ground than I need.
How could I create a simple docker-compose file from the above?
You write following in docker-compose.yml file to run your docker container using compose:
version: '3'
services:
app:
build: .
ports:
- 8080:8080
Docker compose file is made of multiple services but in your case it is enough to define one service. build option specifies from where to pick up the Dockerfile to build the image and ports will allow port forwarding from the container to you host OS.
To start the service you can use:
docker-compose up
And to stop the service:
docker-compose down
You can find more documentation about the compose file here

Resources