Docker is copying the context dir into my workdir - docker

I have this very simple image:
FROM node:11-alpine
WORKDIR /app
COPY src /app/src
RUN cd src \
&& npm i --no-cache \
&& npm run build
CMD cd src \
&& npm run start
Everything is ok during the build, e.g. a simple ls -R / reveals the following tree:
/:
app/
/app:
src/
/app/src:
package.json ...
But when I try to start it I find the following structure:
/:
app/
/app/:
src/
/app/src/:
src/ ... more files from the context dir that I never COPYed
/app/src/src/:
package.json ...
If I RUN ls -R / just after npm run build I get the 'good' tree, even running ls -R / just one layer before CMD I get the same 'good' tree, but any layer after CMD (including CMD itself) gets me the 'wrong' tree, e.g:
CMD ls -R / && cd src && npm run start
It shows /app/src/src, just as if it was taking all the contents of the context dir and putting them below the WORKDIR/src (i.e. /app/src)
Why is docker doing this?
I'm running
Docker version 18.09.3, build 774a1f4
docker-compose version 1.23.2, build 1110ad0

After fiddling around in a somewhat "cleaner" environment at home, I found out that, as a comment suggests, the culprit was a stuck volume, it was mounting ./myapp:/app/src even though such thing was no longer around in the volumes section of my docker-compose.yaml file, and a simple yes|docker system prune did the trick.

Related

docker image is not rebuilt automatically on file change

I am running docker containers with WSL2. When I make changes to my files in the /client directory the changes are not reflected and I have to do docker compose stop client, docker compose build client and docker compose start client. If I cat a file after changing domething one can see the change.
Here is my Dockerfile:
FROM node:16.17.0-alpine
RUN mkdir -p /client/node_modules
RUN chown -R node:node /client/node_modules
RUN chown -R node:node /root
WORKDIR /client
# Copy Files
COPY . .
# Install Dependencies
COPY package.json ./
RUN npm install --force
USER root
I alse have a /server directory with the following Dockerfile and the automatic image rebuild happens on file change there just fine:
FROM node:16.17.0-alpine
RUN mkdir -p /server/node_modules
RUN chown -R node:node /server/node_modules
WORKDIR /server
COPY . .
# Install Dependencies
COPY package.json ./
RUN npm install --force --verbose
USER root
Any help is appreciated.
Solved by adding the following to my docker-compose.yml:
environment:
WATCHPACK_POLLING: "true"
Docker does not take care of the hot-reload.
You should look into the hot-reload documentation of the tools you are building with.

How to copy files into outside working directory

I want to copy the file to a folder location that is outside the working directory. I used the following lines in my docker file, but the files are not there when I look in the container.
WORKDIR /app
RUN cd ../opt/venv/lib/python3.7/site-packages/xxx/
COPY ./resources/abc.py .
When look a that /opt/venv/lib/python3.7/site-packages/xxx/ location the abc.py is not there
What is the issue with my approach? Appreciate your inputs.
You can't COPY a file from outside the build context. So if you are trying to COPY /opt/venv/lib/python3.7/site-packages/xxx/resources/abc.py into your docker image, and that is not in your build context, it will fail. Full stop.
Here's some annotated code.
# change to the /app directory in the container
WORKDIR /app
# run the command cd in the container. cd is a shell builtin, and after
# this command finishes you will still be inside the /app directory in
# your container.
RUN cd ../opt/venv/lib/python3.7/site-packages/xxx/
# Attempt to copy ./resources/abc.py from your host's build context
# (NOT /opt/venv/lib/python3.7/site-packages/xxx/) into the container.
COPY ./resources/abc.py .
The basic fix for this is to first copy abc.py into your build directory. Then you will be able to copy it into your docker container during your build like so:
WORKDIR /app
COPY abc.py .
# /app/abc.py now exists in your container
Note on cd
cd is a shell builtin that changes the working directory of the shell. When you execute it inside a script (or in this case a docker RUN) it only changes the working directory for that process, which ends when the script ends. After which your working directory will be the one you started in. So you cannot use it in the way you were intending. Much better explanation here.
Take this Dockerfile for example:
FROM alpine:latest
RUN cd /opt # cd to /opt
RUN pwd # check current directory, you're STILL in '/'
RUN cd /opt && \
pwd # works as expected because you're still in the same process that cd ran in.
# But once you exit this RUN command you will be back in '/'
# Use WORKDIR to set the working directory in a dockerfile
Here's the output of building that Dockerfile (removed noisy docker output):
$ docker build --no-cache .
Sending build context to Docker daemon 3.584kB
Step 1/4 : FROM alpine:latest
Step 2/4 : RUN cd /opt
Step 3/4 : RUN pwd
/
Step 4/4 : RUN cd /opt && pwd
/opt
From what I understand, you're trying to copy a file into a specific location (/opt/venv/lib/python3.7/site-packages/xxx/) in your Docker image that is outside the WORKDIR you defined in the Dockerfile for your image.
You can easily do this by specifying the absolute destination path in the COPY command:
WORKDIR /app
COPY ./resources/abc.py /opt/venv/lib/python3.7/site-packages/xxx/abc.py

Why Dockerfile builds but is not working correctly, even though it works manually?

I've been trying to get this running for many MANY hours. I've been scouting docker docs, github repos and other stuff but I can't get it working for some reason.
My dockerfile:
FROM mattrayner/lamp:latest-1804
WORKDIR /app
RUN wget -O /tmp/lwt.zip http://downloads.sourceforge.net/project/lwt/lwt_v_1_6_3.zip && \
yes A | unzip /tmp/lwt.zip &&\
rm /tmp/lwt.zip &&\
mv connect_xampp.inc.php connect.inc.php
EXPOSE 80
CMD ["/run.sh"]
It build normally without any errors but when I run the image nothing appears in the /app directory and I get just a basic Welcome to LAMP view on my browser.
Though,
If I do docker run -p "80:80" -it -v ${PWD}/app:/app mattrayner/lamp:latest-1804 /bin/bash, cd /app, copy and paste
wget -O /tmp/lwt.zip http://downloads.sourceforge.net/project/lwt/lwt_v_1_6_3.zip && \
yes A | unzip /tmp/lwt.zip &&\
rm /tmp/lwt.zip &&\
mv connect_xampp.inc.php connect.inc.php
it still doesn't work BUT if I exit and run the same docker run command it works.
Docker LAMP instructions also state to do exactly as I have done:
FROM mattrayner/lamp:latest-1804
# Your custom commands
CMD ["/run.sh"]
As I followed these instructions I thought that everything would work nicely.
What's the catch here? It has something to do with the intermediate containers probably but I can't comprehend it (I'm not a devops or developer by trade, just a hobbyist).
That happens because you're doing this:
Download a file (wget ...) in your /app dir in your docker image.
After that, you're overwritting this /app dir when you mount volume, with content of your $PWD/app.
If you are installing something doing docker build in some dirs, don't mount into the same path.
If you need something in the same path, you can mount some concrete files, but not the whole dir, or it will override what you had in your docker image when container is created.
You can do wget somewhere else or download it into your ${PWD}/app and then mount it.

Docker build "no such file or directory" error

RUN adduser -D appUser
RUN mkdir /usr/share/app
RUN mkdir /logs
ADD Function/target/foo.jar /usr/share/app
WORKDIR /usr/share/app
RUN chown -R appUser /usr/share/app
RUN chown -R appUser /logs
USER appUser
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "foo.jar"]`
I've got this weird issue I can't seem to work my head around.
My root folder contains two directories, (both with subdirectories) 'Demo/Dockerfile' and 'Function/target/foo.jar'
I have a copy command in my Dockerfile that reads
COPY Function/target/foo.bar /usr/share/app
but when I run docker build -f Demo/Dockerfile from the root folder, I get an error
stat /var/lib/docker/tmp/docker-builder238823934/Function/target/foo.jar: no such file or directory
I find this a bit strange because when I edit the copy command to read COPY /target/foo.bar /usr/share/app and then I cd into the Function directory and run
docker build -f ../Demo/Dockerfile
it builds successfully, or if I edit the Dockerfile to read COPY foo.bar /usr/share/app and then cd into the target directory and run docker build -f ../../Demo/Dockerfile, this also works.
Is there an explanation for this sort of behavior?
This is what my dockerignore file looks like
!**/Dockerfile
!DockerServiceDescription/**
!Function/target/*.war
!server.xml
!tomcat-users.xml
Docker uses context directory and children only and does not allow using any files outside for security reasons.
You should show context directory to docker using '.' or so:
cd myproject
docker build -f Demo/Dockerfile .

Running bower install inside a docker volume

Context
So I'm trying to execute build a polymer project inside a docker container as a volume (to access it I'm using docker run (...) --volume="/var/www/html:/var/www/html" --volumes-from="my-polymer-image-name" my-nginx-image).
And I tried execute the following Dockerfile, but declaring the volume last, but the volume was empty when I tried to access it from "my-nginx-container" (docker exec -ti my-nginx-image-name /bin/sh).
So I thought I had to declare the volume before using using it.
Problem
But when I tried to install my bower components, I noticed that no bower_components directory was being created.
########################################################
# Dockerfile to build Polymer project and move to server
# Based on oficial node Dockerfile
########################################################
FROM node:6
VOLUME /var/www/html
# Install polymer and bower
RUN npm install -g \
polymer-cli \
bower
# Add project to a temp folder to build it
RUN mkdir -p /var/www/html/temp
COPY . /var/www/html/temp
WORKDIR /var/www/html/temp
RUN ls -la
RUN bower install --allow-root # here is where I try to build my project
RUN polymer build
# Move to release folder
WORKDIR /var/www/html
RUN mv /var/www/html/temp/build/unbundled/* /var/www/html
RUN bower install --allow-root
# Remove temporary content
RUN rm -rf /var/www/html/temp
Volume mount when docker image build done.
in last row in Docker file add
ENTRYPOINT ["/bin/bash", "/etc/entrypoint.sh"]
Use entripoint script like this.
#!/bin/bash
set -e #if error bash script will exit and stop docker image
cd /var/www/html/
bower install --allow-root
polymer build
mv /var/www/html/temp/build/unbundled/* /var/www/html
rm -rf /var/www/html/temp

Resources