Docker Compose build context from git repository with Dockerfile inside folder - docker

I would like to build a new image in my docker compose project using a git repository as I need to change some ARG vars.
My concern is that the Dockerfile is inside a folder of the git repository.
How can be specified a folder as build context using a git repository?
Repository: https://github.com/wodby/drupal-php/blob/master/7/Dockerfile
version: "2"
services:
php:
build:
context: https://github.com/wodby/drupal-php.git
dockerfile: 7/Dockerfile
args:
- BASE_IMAGE_TAG=7.1
- WODBY_USER_ID=117
- WODBY_GROUP_ID=111
volumes:
- ./:/var/www/html
I've tried the dockerfile property: "FOLDER/" + Dockerfile
But the repository uses relative paths, and it doesn't find dependencies:
---> 6cc2006e9102
Step 7/9 : COPY templates /etc/gotpl/
ERROR: Service 'phpe' failed to build: COPY failed: stat /var/lib/docker/tmp/docker-builder740707850/templates: no such file or directory

It should be this way: myrepo.git#:myfolder
version: "2"
services:
php:
build:
context: https://github.com/wodby/drupal-php.git#:7
args:
- BASE_IMAGE_TAG=7.1
- WODBY_USER_ID=117
- WODBY_GROUP_ID=111
volumes:
- ./:/var/www/html
https://docs.docker.com/engine/reference/commandline/build/#git-repositories

Related

Running docker-compose up ends up with error "Service has neither an image nor a build context specified."

My microservices project structure is like this:
my-service-one/
- Dockerfile
- ...
my-service-two/
- Dockerfile
- ...
docker-compose.yml
As you can see, each service directory contains a Dockerfile. There is a docker-compose.yml in the root level.
The docker-compose.yml :
version: "3"
services:
service-one:
container_name: service-one
build:
dockerfile: ./my-service-one/Dockerfile
ports:
- "8081:8081"
service-two:
container_name: service-two
build:
dockerfile: ./my-service-two/Dockerfile
ports:
- "8082:8082"
Now, I run docker-compose up -d from the root. I end up with error:
$ docker-compose up -d
ERROR: The Compose file is invalid because:
Service service-one has neither an image nor a build context specified. At least one must be provided.
My question is why does docker-compose think my service-one doesn't have a build context specified? Didn't I specify it already with:
build:
dockerfile: ./my-service-one/Dockerfile
Why this error?
why does docker-compose think my service-one doesn't have a build context specified?
Weeeell, because you did not specified the build context.
Didn't I specify it already with:
No, you specified the dockerfile. No the context.
Why this error?
You have to specify the context so that docker knows what to build.
If you want to build with the context of current directory, you would do:
build:
context: .
dockerfile: ./my-service-two/Dockerfile
Maybe the context is inside my-service-two, I suspect youw antto write:
build:
context: ./my-service-two
dockerfile: ./Dockerfile
or really just:
build: ./my-service-two
Peovide a context property below both services in build section like that:
build:
context: YOUR_DIRECTORY
dockerfile: ./my-service-one/Dockerfile
YOUR_DIRECTORY is the place where the files for your project are listed.
Most probably YOUR_DIRECTORY is already written i the child .yml files.
You have a couple of main approaches:
To copy paste the context from the child .yml
To produce the docker build using the child .yml with a command like:
docker-compose -f docker-compose.yml -f docker-compose-dev.yml up
--build

Dockerfile copy jar file from another directory

Ι have this Dockerfile:
FROM openjdk:11
ENV JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
The structure of my application is:
Demo:
--deployment:
--Dockerfile
--src/
--docker-compose.yaml
--target:
--app.jar
Code snippet from docker-compose file:
api:
container_name: backend
image: backend
build:
context: deployment/
ports:
- "8080:8080"
When I am putting the Dockerfile in the same directory with the docker-compose and I am changing the docker compose to:
api:
container_name: backend
image: backend
build: .
ports:
- "8080:8080"
Is running as expected. But I want to put the Dockerfile into the deployment folder, since there I have the helm chart and others docker-comopose files which are using this Dockerfile.
My question is:
How I can specify the correct path of the target folder in the Dockerfile?
You cannot copy anything which is out of the build context. If you want to keep the current project structure a solution would be in your compose file for the api service:
build:
context: .
dockerfile: deployment/Dockerfile

Docker container works, but fails when build from docker-compose

I have an application with 3 containers:
client - an angular application,
gateway - a .NET Core application,
api - a .NET Core application
I am having trouble with the container hosting the angular application.
Here is my Docker file:
#stage 1
FROM node:alpine as node
WORKDIR /app
COPY . .
RUN npm install
RUN npm run build
#stage 2
FROM nginx:alpine
COPY --from=node /app/dist/caliber_client /usr/share/nginx/html
EXPOSE 80
and here is the docker compose file:
# Please refer https://aka.ms/HTTPSinContainer on how to setup an https developer certificate for your ASP .NET Core service.
version: '3.4'
services:
calibergateway:
image: calibergateway
container_name: caliber-gateway
build:
context: .
dockerfile: caliber_gateway/Dockerfile
ports:
- 7000:7000
environment:
- ASPNETCORE_ENVIRONMENT=Development
networks:
- caliber-local
caliberapi:
image: caliberapi
container_name: caliber-api
build:
context: .
dockerfile: caliber_api/Dockerfile
environment:
- ASPNETCORE_ENVIRONMENT=Development
networks:
- caliber-local
caliberclient:
image: caliber-client-image
container_name: caliber-client
build:
context: .
dockerfile: caliber_client/Dockerfile
ports:
- 7005:7005
networks:
- caliber-local
networks:
caliber-local:
external: true
When I build and run the angular container independently, I can connect and run the site, however if I try to build it with docker-compose, I get the following error:
enoent ENOENT: no such file or directory, open '/app/package.json'
I can see that npm cannot find the package.json, but I am copying the whole site to the /app directory in the docker file, so I am not sure where the disconnect is.
Thank you.
In the Dockerfile, the left-hand side of COPY statements is always interpreted relative to the build: { context: } directory in the docker-compose.yml file (or the build: directory if there's not a nested argument, or the docker build directory argument; but in any case never anything outside this directory tree).
In a comment, you say
The package.json is one level deeper than the docker-compose.yml file. It is at the same level of the Dockerfile in the caliber_client folder.
Assuming that client application is self-contained, you can change the build definition to use the client subdirectory as the build context
build:
context: caliber_client
dockerfile: Dockerfile
or, since dockerfile: Dockerfile is the default, the shorter
build: caliber_client
If it's important to you to use the parent directory as the build context (maybe you're including some shared files that you don't show in the question) then you can also change the Dockerfile to refer to the subdirectory.
# when the build: { context: } is the parent directory of this one
COPY caliber_client .

Docker-compose build: How to build an image for production and copy an app code to image?

https://docs.docker.com/compose/production/
Removing any volume bindings for application code, so that code stays
inside the container and can’t be changed from outside
I'd like to build image for production with my app code.
I have a file docker-compose-prod.yml
version: '3'
services:
------
nginx:
build:
context: ./docker/nginx
image: my_nginx:v1
ports:
- 80:80
volumes:
- ./docker/app:/var/www/html
depends_on:
- php
------
The code of my app located in ./docker/app.
The Dockerfile located in ./docker/nginx and I can't with command COPY to copy an app code outside /docker/nginx folder.
When I run a build command I get an image without app contend in /var/www/html:
docker-compose -f docker-compose-prod.yml build
How to build an image in this case with my an app code?
You could pass the dockerfile in the build argument: https://docs.docker.com/compose/compose-file/#dockerfile
This way, I think that you can change your app context to be ./docker, and in the Dockerfile, copy the app folder to /var/www/html. This way, you no longer have to specify a volume when starting the app.
Correct config looks like:
version: '3'
services:
------
nginx:
build:
context: ./docker
dockerfile: nginx/Dockerfile-prod
image: my_nginx:v1
ports:
- 80:80
------
And the Dockerfile-prod in /docker/nginx
...
COPY ./app /var/www/html
...

Dockerfile pass environments on docker compose build

I have written a Dockerfile which uses two arguments:
FROM jessie
MAINTAINER Zeinab Abbasimazar
#Build Arguments
ARG REP_USER
ARG REP_PASS
# Build
RUN echo 'REP_USER:'$REP_USER', REP_PASS:'$REP_PASS
I wrote a docker-compose.yml for build:
version: "2"
services:
ui:
build:
context: .
dockerfile: Dockerfile
args:
REP_USER: $REP_USER
REP_PASS: $REP_PASS
I don't want to define these arguments directly in the compose file, so I tried to send them during docker compose build:
REP_USER=myusername REP_PASS=mypassword docker-compose build
Which didn't work. I changed my Dockerfile to use these arguments as environment variables; so I removed ARG lines:
FROM jessie
MAINTAINER Zeinab Abbasimazar
# Build
RUN echo 'REP_USER:'$REP_USER', REP_PASS:'$REP_PASS
And docker-compose.yml:
version: "2"
services:
ui:
build:
context: .
dockerfile: Dockerfile
And ran REP_USER=myusername REP_PASS=mypassword docker-compose build; still no result.
I also tried to save these information into an env file:
version: "2"
services:
ui:
build:
context: .
dockerfile: Dockerfile
env_file:
- myenv.env
But it seems env files doesn't affect at build time; they are just take part into run time.
EDIT 1:
Docker version is 1.12.6 which doesn't support passing arguments with --build-arg.
EDIT 2:
I tried using .env file as described here:
cat .env
REP_USER=myusername
REP_PASS=mypassword
I then called docker-compose config which returned:
networks: {}
services:
ui:
build:
args:
REP_PASS: mypassword
REP_USER: myusername
context: /home/zeinab/Workspace/ZiZi-Docker/Test/test-exec-1
dockerfile: Dockerfile
version: '2.0'
volumes: {}
Which means this resolved my issue.
EDIT 3:
I also tried third section of docker-compose arg documentation in my docker-compose.yml file:
version: "2"
services:
ui:
build:
context: .
dockerfile: Dockerfile
args:
- REP_USER
- REP_PASS
And executed:
export REP_USER=myusername;export REP_PASS=mypassword;sudo docker-compose build --no-cache
Still not getting what I wanted.
You can set build arguments with docker compose as described here:
docker-compose build [--build-arg key=val...]
docker-compose build --build-arg REP_USER=myusername --build-arg REP_PASS=mypassword
Btw, AFAIK build arguments are a compromise between usability and deterministic building. Docker aims to build in a deterministic fashion. That is, wherever you execute the build the produced image should be the same. Therefore, it appears logical that the client ignores the environment (variables) it is executed in.
The correct syntax for variable substitution in a docker-compose file is ${VARNAME}.
Try with this one:
version: "2"
services:
ui:
build:
context: .
dockerfile: Dockerfile
args:
REP_USER: ${REP_USER}
REP_PASS: ${REP_PASS}
I finally found the solution. I mentioned it in the question too. I first tried it with fail, then I found out that I had a typo naming .env file; it was .evn.
I tried using .env file as described here:
cat .env
REP_USER=myusername
REP_PASS=mypassword
I then called docker-compose config which returned:
networks: {}
services:
ui:
build:
args:
REP_PASS: mypassword
REP_USER: myusername
context: /home/zeinab/Workspace/ZiZi-Docker/Test/test-exec-1
dockerfile: Dockerfile
version: '2.0'
volumes: {}
Which means this resolved my issue. I should mention that this answer was really helpful.

Resources