Docker compose with name other than dockerfile - docker

I have used docker to create CLI interfaces where I test my code. These are named reasonably as:
proj_root/.../docks/foo.dockerfile
proj_root/.../docks/bar.dockerfile
Because there is more than one dock involved, the top level "Dockerfile" at the project root is unreasonable. Although I can't copy ancestor directories when building in docker, I can clone my entire repo.
So my project architecture works for me.
Next, I look up docker-compose because I need to match my docker cards up against a postgres db and expose some ports.
However, docker-compose seems to be anchored to the hard-coded '"Dockerfile" in the current working directory' user concept from the perspective of the command line interface.
But! I see the error message implies the tool is capable of looking for an arbitrarily named dockerfile:
ERROR: Cannot locate specified Dockerfile: Dockerfile
The question is: how do I set docker-compose off looking for foo.dockerfile rather than ./Dockerfile?

In your docker-compose, under the service:
services:
serviceA:
build:
context: <folder of your project>
dockerfile: <path and name to your Dockerfile>

As mentioned in the documentation of docker-compose.yml, you can overwrite the Dockerfile filename within the build properties of your docker-compose services.
For example:
version: 3
services:
foo:
image: user/foo
build:
context: .../docks
dockerfile: foo.Dockerfile
bar:
image: user/bar
build:
context: .../docks
dockerfile: bar.Dockerfile

Related

Why does building and image with docker compose fail but succeeds without it?

I am trying to build an image with docker compose and it fails, however it works with just docker. I have read some SO posts saying that the error thrown when failing happens when a file/folder cannot be found in the Dockerfile. The build works when building with docker so I dont know why it wouldn't work with docker-compose. Why is this happening?
The structure for this project is this:
parent_proj
|_proj
|_Dockerfile
|_docker-compose.yml
Here is my docker-compose file:
version: '3.4'
services:
integrations:
build:
context: .
dockerfile: proj/Dockerfile
network: host
image: int
ports:
- "5000:5000"
Here is the Dockerfile inside proj/
FROM openjdk:11
USER root
#RUN apt-get bash
ARG JAR_FILE=target/proj-0.0.1-SNAPSHOT.jar
COPY ${JAR_FILE} /app2.jar
ENTRYPOINT ["java","-jar", "/app2.jar"]
When I'm inside the proj folder. I can run
docker build . -t proj
The above succeeds and I can subsequently run the container. However when I am in parent_proj and run docker compose build it fails with the error message
failed to compute cache key: failed to walk
/var/lib/docker/tmp/buildkit-mount316454722/target: lstat
/var/lib/docker/tmp/buildkit-mount316454722/target: no such file or
directory
Why does this happen? How can I build successfully with docker-compose without restructuring the project?
thanks
Your Compose build options and the docker build options you show are different. The successful command is (where -f Dockerfile is the default):
docker build ./proj -t proj # -f Dockerfile
# context: image: dockerfile:
But your Compose setup is running
docker build . -t img -f proj/Dockerfile
# context: image: dockerfile:
Which one is right? In the Dockerfile, you
COPY target/proj-0.0.1-SNAPSHOT.jar /some/container/path
That target/... source path is always relative to the build-context directory (Compose context: option, the directory parameter to docker build), even if it looks like an absolute path and even if the Dockerfile is in a different directory. If that target directory is a subdirectory of proj then you need the first form.
There's a shorthand Compose build: syntax if the only thing you need to specify is the context directory, and I'd use that here. If you don't specifically care what the image name is (you're not pushing it to a registry) then Compose can pick a reasonable name on its own; you don't need to specify image:.
version: '3.8'
services:
integrations:
build: ./proj
ports:
- "5000:5000"

Docker Volume is not working for deployments

I am following lynda Docker tutorials and performing stuff related to docker compose file.
This is my docker-compose.yml file.
more docker-compose.yml
version: '3'
services:
web:
image: jboss/wildfly
volumes:
- ~/deployments:/opt/jboss/wildfly/standalone/deployments
ports:
- 8080:8080
As per authors, I am trying to copy webapp.war file to deployments/ folder giving me error. It look like volume mapping for the docker file is not working.
cp /home/user/Demos/docker-for-java/chapter2/webapp.war deployments/
cp: cannot create regular file ‘deployments/’: Not a directory
docker-compose ps
Name Command State Ports
--------------------------------------------------------------------------------
helloweb_web_1 /opt/jboss/wildfly/bin/sta ... Up 0.0.0.0:8080->8080/tcp
I think you might be misinterpreting tutorial. I haven't seen the tutorial itself, but checking the documentation for the WildFly Docker image here there's a mention that you need to extend base image and add your war file inside:
To do this you just need to extend the jboss/wildfly image by creating a new one. Place your application inside the deployments/ directory with the ADD command (but make sure to include the trailing slash on the deployment folder path, more info). You can also do the changes to the configuration (if any) as additional steps (RUN command).
This means that you need to create a Dockerfile with approximately this contents (change your-awesome-app.war with the path to your war file):
FROM jboss/wildfly
ADD your-awesome-app.war /opt/jboss/wildfly/standalone/deployments/
After that you need to change you docker-compose.yml to build from your Dockerfile instead of using jboss/wildfly (note the use of build: . instead of image: jboss/wildfly):
version: '3'
services:
web:
build: .
ports:
- 8080:8080
Try that and comment if you run into any issues

Referencing files outside of build context

I would like to organize my docker image files based on the service i'm building in a .docker directory. To start, I'd like to build out the web docker container. Note how in the docker file, I am copying the webroot files to the docker container. The issue is, in my docker-compose.yml, when the image gets built, it references the root from the .docker/web directory instead of the actual webroot. I tried using a relative path in the docker file which didn't seem to work. Any ideas how I can accomplish this?
version: '3'
services:
web:
build:
context: .docker/web
dockerfile: Dockerfile
Dockerfile
FROM webdevops/php-apache-dev
ADD ./../../ /var/www/html
Error
ERROR: Service 'web' failed to build: ADD failed: Forbidden path outside the build context: ../../
It would be helpful to see more of the directory tree you're working with, but I'll make a guess at what you're trying to do.
The context setting in docker-compose.yml defines the starting point for relative paths passed as the first argument to ADD, and relative paths can't point to directories higher than that in the tree. If I understand your case correctly, you should be able to do:
version: '3'
services:
web:
build:
context: .
dockerfile: .docker/web/Dockerfile
And change your Dockerfile to have:
ADD . /var/www/html

What is the difference between `docker-compose build` and `docker build`?

What is the difference between docker-compose build and docker build?
Suppose in a dockerized project path there is a docker-compose.yml file:
docker-compose build
And
docker build
docker-compose can be considered a wrapper around the docker CLI (in fact it is another implementation in python as said in the comments) in order to gain time and avoid 500 characters-long lines (and also start multiple containers at the same time). It uses a file called docker-compose.yml in order to retrieve parameters.
You can find the reference for the docker-compose file format here.
So basically docker-compose build will read your docker-compose.yml, look for all services containing the build: statement and run a docker build for each one.
Each build: can specify a Dockerfile, a context and args to pass to docker.
To conclude with an example docker-compose.yml file :
version: '3.2'
services:
database:
image: mariadb
restart: always
volumes:
- ./.data/sql:/var/lib/mysql
web:
build:
dockerfile: Dockerfile-alpine
context: ./web
ports:
- 8099:80
depends_on:
- database
When calling docker-compose build, only the web target will need an image to be built. The docker build command would look like :
docker build -t web_myproject -f Dockerfile-alpine ./web
docker-compose build will build the services in the docker-compose.yml file.
https://docs.docker.com/compose/reference/build/
docker build will build the image defined by Dockerfile.
https://docs.docker.com/engine/reference/commandline/build/
Basically, docker-compose is a better way to use docker than just a docker command.
If the question here is if docker-compose build command, will build a zip kind of thing containing multiple images, which otherwise would have been built separately with usual Dockerfile, then the thinking is wrong.
Docker-compose build, will build individual images, by going into individual service entry in docker-compose.yml.
With docker images, command, we can see all the individual images being saved as well.
The real magic is docker-compose up.
This one will basically create a network of interconnected containers, that can talk to each other with name of container similar to a hostname.
Adding to the first answer...
You can give the image name and container name under the service definition.
e.g. for the service called 'web' in the below docker-compose example, you can give the image name and container name explicitly, so that docker does not have to use the defaults.
Otherwise the image name that docker will use will be the concatenation of the folder (Directory) and the service name. e.g. myprojectdir_web
So it is better to explicitly put the desired image name that will be generated when docker build command is executed.
e.g.
image: mywebserviceImage
container_name: my-webServiceImage-Container
example docker-compose.yml file :
version: '3.2'
services:
web:
build:
dockerfile: Dockerfile-alpine
context: ./web
ports:
- 8099:80
image: mywebserviceImage
container_name: my-webServiceImage-Container
depends_on:
- database
Few additional words about the difference between docker build and docker-compose build.
Both have an option for building images using an existing image as a cache of layers.
with docker build, the option is --cache-from <image>
with docker-composer, there is a tag cache_from in the build section.
Unfortunately, up until now, at this level, images made by one are not compatible with the other as a cache of layers (Ids are not compatible).
However, docker-compose v1.25.0 (2019-11-18), introduces an experimental feature COMPOSE_DOCKER_CLI_BUILD so that docker-compose uses native docker builder (therefore, images made by docker build can be used as a cache of layers for docker-compose build)

context or workdir for docker-compose

I'm learning docker
I need to specify the working directory for a docker image, I think that'll be something like this:
version: '2'
services:
test:
build:
context: ./dir
Now I want to make the image python:onbuild to run on the ./dir, but I dont want to create any Dockerfile inside the ./dir.
The docker-compose manual says nothing about that.
Is it possible? How to do that?
I think you're looking for working_dir. Search for "working_dir" in the docker-compose reference.
You can specify the working directory as follows.
version: '2'
services:
test:
build:
context: /path/to/source/dir/
dockerfile: /path/to/custom-Dockerfile/relative/tocontextdir/Dockerfile
working_dir: /app
Possibly not exactly what you were looking for, but you can specify the "context" for the docker build to be a different directory to where the actual Dockerfile lives.
build:
context: ./folder/containing/files
dockerfile: path/to/dockerfile/relative/to/context/Dockerfile
Any ADD/COPY commands in your Dockerfile then act as if they are relative to the context regardless of where the Dockerfile actually is.
The build configuration in Docker Compose just ends up in a call to docker build, so you need to have a Dockerfile to use that workflow.
As the docs for python:onbuild say, you can start with a minimal Dockerfile that just contains FROM python:onbuild. But as they also say, :onbuild isn't a great option, you'll have much more control building your own Dockerfile FROM python.

Resources