Is there a way to automatically "Rebase" an image in Docker? - docker

I have a docker-compose script that brings up a service
version : '2.0'
services:
orig-db:
image: web-url:{image_tag}
custom-db:
image: local_image: latest
Where image used in custom DB is the the result of bringing up a container with orig-db, performing some basic bash commands, and doing a docker commit. I want the custom-db image to always be the original image + these commands, even if the original image is updated. Is there a way to "rebase" off the original image?

You can think of a Dockerfile as a simple form of a "rebase".
# Content of subdir/Dockerfile
FROM orig_image:latest
RUN some.sh
RUN basic.sh
RUN bash_commands.sh
When you build an image based on this file, it will always run the bash commands on top of the base image. Inside the compose file you can use the build property to instruct docker-compose to build the image instead of using a pre-made image.
version : '2.0'
services:
orig-db:
image: web-url:{image_tag}
custom-db:
build: somedir
If the base image changes, you need to tell docker-compose to rebuild the custom-db image again, running the bash commands again on top of the updated original image.
docker-compose up -d --build custom-db

Related

Docker Container (Website) Content not Updating

I have built a project with a webhost (httpd:2.4)
(Dockerfile Content:
FROM httpd:2.4
COPY . /usr/local/apache2/htdocs )
It's hosting a static website... and I'd like to be able to change that / publish future changes but that doesn't work in the way I was expecting it to...
I'm using
git clone [repository]
cd [repository]
docker-compose -f docker-compose/docker-compose.yml up -d
to run the project, which works perfectly fine
The problem is that I should be able to make changes to the website.
I supposed it would just work like that:
docker-compose -f docker-compose/docker-compose.yml down
changing the index.html (save)
docker-compose -f docker-compose/docker-compose.yml up -d
But even though (for the test) I deleted every single character in my index.html, it still shows up exactly the same as before
What am I missing? What commands would I have to run for the changes to get applied?
If you have a dockerfile, the file containing the below,
FROM httpd:2.4
COPY . /usr/local/apache2/htdocs
It means you are building a custom docker image for your need. And you are also using the COPY command to copy the project to your docker image which is done when building the custom docker image. This is a good solution to copy the code in the docker image for distribution purposes however might not be the best for development purposes.
If changes are made to the project, this is not reflected in the custom docker image until that docker image is rebuilt. After rebuilding the image, the current files of the project are copied to the docker image. Then after restarting the docker compose and by also using the latest image built, the changes will be visible.
If you do not want to build a docker image each time a change is made, it might be best to create a docker-compose file which will map your project directly to /usr/local/apache2/htdocs. This way when the changes made to the project will be reflected instantly without any build process.
Sample docker compose file with the project mapping to /usr/local/apache2/htdocs, this docker compose file needs to be located in the directory where the index.html lives.
version: '3.9'
services:
apache:
image: httpd:latest
container_name: webserver
ports:
- '8080:80'
volumes:
# mapping your root project's directory to htdocs
- ${PWD}:/usr/local/apache2/htdocs
This problem may arise if you have referenced a docker image inside your docker-compose.yml file instead of building the image there. When you reference an image, docker-compose up will create the corresponding containers with the exact same image.
You need to:
Build the image again AFTER you have made changes to your html file and BEFORE running docker-compose.
OR
Build the image inside docker-compose.yml like this

Docker Always force to use a cached image

I'm using docker compose to build my application using docker.
Version of docker-compose is 2.2
I have all the containers running well at the moment where one of the container has nginx running.
I need to change some configuration on this container.
The way I need to do (because of special scenario) is, to update the config inside the container.
Then I commit the container to build a new image.
docker commit <container> <image-name>
Now I have new image with tag latest.
What I want is to use this image when I run, docker-compose down && docker-compose up --build next time.
docker-compose down && docker-compose up --build -d
With --build option, docker-compose will go through the steps in Dockerfile and run those and all my changes will be reverted.
Question:
Is there anyway that I can tell docker-compose to use the newly created image as cache and ignore Dockerfile for this one container?
Solution Tried:
I have tried with docker-compose-override and using option cache-from and it's not working.
docker-compose.override.yml
container:
build:
cache_from:
- new-image:latest
Thanks in advance.
I don't understand why you would want to build an image from docker-compose even though you have already built it by docker-commit.
Now I have new image with tag latest.
What I want is to use this image when I run, docker-compose down && docker-compose up
If you have already built image, skip the build phase in docker-compose. Just specify which image should be used like so:
container:
image: new-image:latest
container_name: "Foo bar"
.....(other options)
Image
Specify the image to start the container from. Can either be a
repository/tag or a partial image ID.
image: redis
image: ubuntu:14.04
image: tutum/influxdb
image: example-registry.com:4000/postgresql
image: a4bc65fd
If the image does
not exist, Compose attempts to pull it, unless you have also specified
build, in which case it builds it using the specified options and tags
it with the specified tag.
If you have any other images that you build from inside docker-compose run:
docker-compose build && docker-compose up
If not simple docker-compose up will suffice.

reuses image built by docker

I built image using
docker build -t my-image
docker-compose.yml has
django:
build:
context: .
dockerfile: ./compose/django/Dockerfile-dev
image: my-image
Then I run docker-compose build
I see my-image is being built again even though I built it previously.
Can an image built by docker build be used by docker-compose ?
What you have written
As the docs say:
If you specify image as well as build, then Compose names the built image with the webapp and optional tag specified in image:
How to avoid this
If you want to rebuild each time
Build as you are, and the build artifact will be saved with the name my-image
If you want to reuse the build
Change to just specify the image to use
If you only want to build if the image doesn't exist
Run compose with --no-build as this describes

Docker - max depth exceeded

So I am using this example:
https://github.com/mcmoe/mssqldocker
In order to create a SQL Server image and load it with data. I have several sql scripts which I run when I run the container.
However, I started getting this error when building the image:
Step 7/9 : ENTRYPOINT ./entrypoint.sh
---> Running in c8c654f6a630
max depth exceeded
I'm not sure how to fix this, I restarted docker and even updated it.
I read something about 125 layers? Can anyone explain the cause of this and a potential fix?
I found this command to run:
docker history microsoft/mssql-server-linux:latest | wc -l
312
My docker-compose yml:
version: "3"
services:
mssql:
build: .
image: 'microsoft/mssql-server-linux'
ports:
- '1433:1433'
environment:
- ACCEPT_EULA=Y
- SA_PASSWORD=Abcgfgh123!
volumes:
- db_volume:/var/lib/mssql/data
volumes:
db_volume:
The image parameter for a service in a docker-compose.yml definition has dual meanings depending on the existence of a build parameter.
If there is no build stanza, The image will just be pulled and run.
If you have a build stanza, image will be the name your built
image is tagged as, and run.
By naming the built image microsoft/mssql-server-linux, which is the same as the FROM microsoft/mssql-server-linux image. Docker was layering the build on top of itself each time.
The original build started on the "official" microsoft/mssql-server-linux but then each subsequent build would start from your local microsoft/mssql-server-linux image which had been appended to, until eventually you hit the maximum number of layers for your storage driver.
Use your own namespace for all images you build:
version: "3"
services:
mssql:
build: .
image: 'user3437721/mssql-server-linux'
Delete all local docker images related to your dockerfile using the following and try again.
$ docker rmi -f $(docker images -a -q)
I was already using a custom image name like in the accepted answer, and I still had this issue.
In order to get past this error, I found that I needed to remove all unused (not associated with any container) and dangling (old image after a new one is made) docker images with the following command:
docker image prune -a
See https://linuxhandbook.com/remove-docker-images/
If this error pops for specific images, then you might want to take a look at the number of layers that exist in your said docker image. When doing changes to a Docker image, each change is getting added as a layer regardless the size increase in the image. I have come across scenarios where my docker images having multiple layers and failing to push in Jenkins jobs. The workaround is to use the same context in the docker image but with reduced amount of layers. For that you can simply take out the content of the image and port them into a new image with a new image name, which will result the same content in a new image and with less amount of layers. Use this tip across scenarios that is helpful. Thanks
for my situation the error was due to \r. I am running windows host and the linux image needs to run an script file for entrypoint which is copied from windows to docker image. during this process the script end lines were changed from \n to \r\n which resulted in this error. undoing this made the error go away.
Prefix the image: in docker-compose.yml with a unique custom name like "my-custom-prefix/..."
# docker-compose.yml
services:
mssql:
build: .
image: my-custom-prefix/mssql-server-linux
...
Just making sure it is not the same as the FROM on top of your Dockerfile (build file)
# Dockerfile
FROM microsoft/mssql-server-linux
...
The same goes for a .lando.yml file. That was the case for me at least.

ordered build of nested docker images with compose

I am building a lamp with docker-compose.
In my docker-compose.yml i have the following:
ubuntu-base:
build: ./ubuntu-base
webserver-base:
build: ./webserver-base
webserver-base is derived from the ubuntu-base image.
In webserver-base Dockerfile:
FROM docker_ubuntu-base
ubuntu-base is built
FROM ubuntu:14.04
Now, if i execute the docker-compose.yml, it does not build the ubuntu-base image, but its trying to build the webserver-base image and fails, because it does not find the ubuntu-base image.
Output:
$ docker-compose up -d
Building webserver-base
Step 1 : FROM docker_ubuntu-base
Pulling repository docker.io/library/docker_ubuntu-base
ERROR: Service 'webserver-base' failed to build: Error: image library/docker_ubuntu-base:latest not found
It all works if i build the ubuntu-base image manually first.
why does it not build the ubuntu-base image?
Sadly, build ordering is a missing feature in docker-compose, that is requested for many month now.
As workaround you can link the containers like this:
ubuntu-base:
build: ./ubuntu-base
webserver-base:
build: ./webserver-base
links:
- ubuntu-base
this way ubuntu-base gets built before webserver-base.
First do a
docker-compose build ubuntu-base
But this will not create the image docker_ubuntu-base locally because you do not have any build steps. Only docker.io/ubuntu:14.04 will be downloaded.
If you add a build step like:
FROM ubuntu:14.04
RUN date
A docker_ubuntu-base image will be created.
So first do a:
docker-compose build ubuntu-base
This will create the image docker_ubuntu-base. Then you can do a docker-compose build.
But I would advise against this nested-docker image construction. This is cumbersome because as #kev indicated you have no control over the order of the builds. Why don't you create two independent docker files? Let docker derive webserver-base from ubuntu-base by keeping the Dockerfile instructions as identical as possible and reusing the layers.

Resources