Docker ADD and COPY not honored in Dockerfile - apache

When I try to build the following Dockerfile, the ADD and COPY steps do nothing:
# Use an official Apache runtime as a parent image
FROM amd64/httpd
# Set the working directory
WORKDIR /usr/local/apache2
# Copy the following contents into the container
ADD ./httpd.conf {$workdir}/conf/httpd.conf
COPY ./Projects/RavensHomeSupport/build/* {$workdir}/htdocs/Test/
# Make port 80 available to the world outside this container
EXPOSE 80
# Define environment variable
ENV NAME RavensHomeWeb
I run the following build command:
docker build -t ravenshome --rm --no-cache .
and when I check the contents of the Test directory in the running container, none of the data that I expected has been copied across to the container. The output of the build command is here.
Sending build context to Docker daemon 1.444MB
Step 1/6 : FROM amd64/httpd
---> 19459a872194
Step 2/6 : WORKDIR /usr/local/apache2
---> Running in 192cb44f767e
Removing intermediate container 192cb44f767e
---> d9816ea17258
Step 3/6 : ADD ./httpd.conf {$workdir}/conf/
---> 19f48db970bb
Step 4/6 : COPY ./Projects/RavensHomeSupport/build/ {$workdir}/htdocs/Test/
---> d93939218c2b
Step 5/6 : EXPOSE 80
---> Running in 43b9e9297f60
Removing intermediate container 43b9e9297f60
---> 3b994be07747
Step 6/6 : ENV NAME RavensHomeWeb
---> Running in a64bccaf81c8
Removing intermediate container a64bccaf81c8
---> 9217c242868c
Successfully built 9217c242868c
Successfully tagged ravenshome:latest
I start the container with the following command:
docker run -dit -p 8080:80 --name ravenshome ravenshome
When I examine the problem directory in the container with the following command:
docker exec ravenshome ls -a /usr/local/apache2/htdocs
I get the following result:
.
..
index.html
As you can see, all that was there is the contents of the default image, not the additional content that I expected.
Similarly, my customized version of httpd.conf is not copied to the new container.
I have read several posts that suggest that the problem is due to using volumes, but I am not doing so, nor do I have a .dockerignore file.
Can anyone see what I am doing wrong?

$workdir isn't a defined environment variable, so it expands to an empty string. $variable inside curly braces isn't special syntax at all; it expands to the variable expansion, inside curly braces. The net result of this is that these two lines:
WORKDIR /usr/local/apache2
ADD ./httpd.conf {$workdir}/conf/httpd.conf
copy content into a directory /usr/local/apache2/{}/conf/http.conf -- nothing is inside the curly braces, and the curly braces themselves are interpreted as a directory relative to the current working directory.
You don't need an environment variable here at all; you can just COPY to the current WORKDIR
WORKDIR /usr/local/apache2
ADD ./httpd.conf ./conf/httpd.conf
COPY ./Projects/RavensHomeSupport/build/* ./htdocs/Test/
See also Variable substitution in the docker-compose.yml documentation for the allowed forms; you're probably thinking of ${variable} syntax (dollars outside the curly braces).

Related

Variable substitution is not happening inside Containerfile

Building a docker container
Using alpine as build image
The Containerfile receives VERSION as argument
It is set as image version
The same version is passed to dotnet publish command.
The passed version (which is a variable) in current context never gets substituted. Instead of substituted variable ${VARIABLE} is passed to dotnet publish command.
ARG VERSION
FROM mcr.microsoft.com/dotnet/sdk:6.0-alpine as build
ARG VERSION
RUN echo ${VERSION}
RUN echo ${VERSION} > image_version
WORKDIR /app
COPY . .
RUN dotnet restore
# TODO Pass the version as build command below.
RUN dotnet publish --version-suffix ${VERSION} --output /app/published-app
I tried different ways to do the variable substitution like below:
"$VERSION"
"$(VERSION)"
$VERSION ..... and many other ways I found in the internet. None of them worked. The argument passed is exactly what it is before the variable is substituted.
Thoughts on what may be causing this?

Variable Substitution with Bamboo in Dockerfile

My Dockerfile looks like the following:
from httpd:${bamboo.test.tag}
COPY index.html /usr/local/apache2/htdocs/
In Bamboo I have a task with the following script:
docker build --no-cache -t myproj/my .
When running the job, I get the following error:
build 26-Sep-2022 10:42:26 Step 1/2 : from httpd:${bamboo.test.tag}
error 26-Sep-2022 10:42:26 failed to process "httpd:${bamboo.test.tag}": missing ':' in substitution
How can I substitute the tag?
This is actually a problem with how you are using the dockerfile.
Docker will not expand environment variables inside your Dockerfile. You need to pass the environment value as a build argument in the docker build command then use the ARG keyword inside the Dockerfile.
Your Dockerfile would look like this:
ARG IMAGE_TAG
from httpd:${IMAGE_TAG}
COPY index.html /usr/local/apache2/htdocs/
And you would need to change you docker build command to:
docker build --no-cache --build-arg IMAGE_TAG=${bamboo.test.tag} -t myproj/my .
Check a more detailed explanation here

Bind path in singularity using container environment variable

I have a singularity container built with a scientific filesystem app.
I run the container with singularity run --app myapp image.sif and, accordingly, I have the environment variable SCIF_APPDATA=/scif/data/myapp set inside the container.
I'd like to bind a path using this environment variable. Something like:
singularity run -B /my/path/on/host/:$SCIF_APPDATA/input/
Unfortunately this does not work. I didn't manage to make singularity use as a mount path the environment variable with its "internal" value.
I have to explicitly pass the value of the environment variable:
singularity run -B /my/path/on/host/:/scif/data/myapp/input
Does anybody know how to use container environment variables in bind paths?
I don't think it is possible to directly use environment variables from inside the container in the bind statement. However, you can do it in two steps, first a call to singularity exec to get the value of the variable, then use it with singularity run:
SCIF_APPDATA=$(singularity exec ascisoftApp.sif bash -c "echo \$SCIF_APPDATA")
singularity run -B /my/path/on/host/:$SCIF_APPDATA/input/ ...
Don't forget the backslash to escape the $ in the echo command.
Note: Not sure why but it doesn't work for me when I directly use echo, hence the wrapping with bash -c.

Docker/Compose: Define and use env variable

on my github i'm creating a little fork from a debian minimal docker image. Its actually 5 packages which build up on previous:
debian-base-minimal
debian-base-standard
debian-base-security
debian-base-apache
debian-base-apache-php
On debian-base-apache i want to get a working env variable, which i can define later in docker-compose file. What should the env do?
Its should, if defined over docker-compose, write ServerName $SERVER_NAME at the end of /etc/apache2/apache2.conf to set a globally Server Name. If empty, no new line should be written.
But why its should write nothing when its empty? Cauz on build the Dockerfile to an image shouldnt include the SERVER_NAME.
I already tried something like:
echo "ServerName $SERVER_NAME" >> /etc/apache2/apache2.conf
on my 040-debian-base-apache file. But on build its wrote ServerName in, cauz i didnt defined a value and its using null. If i set a default in Dockerfile (ENV SERVER_NAME=127.0.0.1) its build the image with 127.0.0.1 and i cant change 127.0.0.1 via variable, cauz the variable already filled in with the value.
On ouput of the building with defined ENV SERVER_NAME=127.0.0.1 in Dockerfile (actually not in repo):
[...]
+ echo 'ServerName 127.0.0.1'
+ /etc/init.d/apache2 stop
Stopping Apache httpd web server: apache2.
ok.
+ /etc/init.d/apache2 start
Starting Apache httpd web server: apache2.
ok.
[...]
Its would be okay, if there stands default 127.0.0.1 cauz the apache can start. But i cant define it now in docker-compose.yml cauz its hardcoded 127.0.0.1 and not the output of a variable.
On ouput of the building with none defined ENV in Dockerfile (actually repo version):
[...]
+ echo 'ServerName '
+ /etc/init.d/apache2 stop
Stopping Apache httpd web server: apache2.
+ /etc/init.d/apache2 start
Starting Apache httpd web server: apache2 failed!
The apache2 configtest failed. ... (warning).
Output of config test was:
AH00526: Syntax error on line 228 of /etc/apache2/apache2.conf:
ServerName takes one argument, The hostname and port of the server
[...]
Can anybody help me to get this working? Would be nice to understand how it works.
Many thanks in advance.
As you've observed, every RUN command in the Dockerfile happens at docker build time, and in particular the contents of the file will be fixed based on what the environment variable was when you ran the build. You want it to change based on the runtime value of the variable, which means you need to write a script that runs at startup to do this.
A typical approach is to write an ENTRYPOINT script that does the first-time setup. The ENTRYPOINT gets passed the CMD (or whatever command got passed into docker run) as command-line arguments, so if it ends with exec "$#", the last thing it does is launch the "normal" command. You can use any ordinary shell script logic here, so I might write
#!/bin/sh
if [ -n "$SERVER_NAME" ]; then
echo "ServerName $SERVER_NAME" >> /etc/apache2/apache2.conf
fi
exec "$#"
Then you can provide this in your Dockerfile
COPY entrypoint.sh /
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
CMD ["apachectl", "-DFOREGROUND"]
(The chmod isn't necessary if you can guarantee the file has execute permissions on your non-Windows host. The ENTRYPOINT must use the JSON-ish form. If you have another image that builds on top of this, remember that the combined image gets only one ENTRYPOINT and one CMD; the very deep stack of images you suggest is a pretty unusual setup.)

How to build docker image from github repository

In official docs we can see:
# docker build github.com/creack/docker-firefox
It just works fine to me. docker-firefox is a repository and has Dockerfile within root dir.
Then I want to buid redis image and exact version 2.8.10 :
# docker build github.com/docker-library/redis/tree/99c172e82ed81af441e13dd48dda2729e19493bc/2.8.10
2014/11/05 16:20:32 Error trying to use git: exit status 128 (Initialized empty Git repository in /tmp/docker-build-git067001920/.git/
error: The requested URL returned error: 403 while accessing https://github.com/docker-library/redis/tree/99c172e82ed81af441e13dd48dda2729e19493bc/2.8.10/info/refs
fatal: HTTP request failed
)
I got error above. What's the right format with build docker image from github repos?
docker build url#ref:dir
Git URLs accept context configuration in their fragment section,
separated by a colon :. The first part represents the reference that
Git will check out, this can be either a branch, a tag, or a commit
SHA. The second part represents a subdirectory inside the repository
that will be used as a build context.
For example, run this command to use a directory called docker in the
branch container:
docker build https://github.com/docker/rootfs.git#container:docker
https://docs.docker.com/engine/reference/commandline/build/
The thing you specified as repo URL is not a valid git repository. You will get error when you will try
git clone github.com/docker-library/redis/tree/99c172e82ed81af441e13dd48dda2729e19493bc/2.8.10
Valid URL for this repo is github.com/docker-library/redis. So you may want to try following:
docker build github.com/docker-library/redis
But this will not work too. To build from github, docker requires Dockerfile in repository root, howerer, this repo doesn't provide this one. So, I suggest, you only have to clone this repo and build image using local Dockerfile.
One can use the following example which sets up a Centos 7 container for testing ORC file format. Make sure to escape the # sign:
$ docker build https://github.com/apache/orc.git\#:docker/centos7 -t orc-centos7