inotifywait with Docker command and variable - shell

I am trying to create a shell script that will check for a new file then cp to a Docker Container. The code I have so far is...
#!/bin/sh
source="/var/www/html/"
dest="dev_ubuntu:/var/www/html/"
inotifywait -m "/var/www/html" -e create -e moved_to |
while read file; do
sudo docker cp /var/www/html/$file dev_ubuntu:/var/www/html
done
But this code gives the following error:
Setting up watches.
Watches established.
"docker cp" requires exactly 2 argument(s).
See 'docker cp --help'.
Usage: docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-
docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH
Copy files/folders between a container and the local filesystem
What am I doing wrong?

Do you have spaces in your file names? Use double quotes to avoid separating filenames by words:
echo $file
sudo docker cp "$file" dev_ubuntu:"$file"
I've also echoed the file name to see what is happening.

Related

Docker container unable to ignore the EntryPoint bash script failure

Bash script:
clonePath=/data/config/
git branch -r | fgrep -v 'origin/HEAD' | sed 's| origin/|git checkout |' > checkoutAllBranches.sh
chmod +x checkoutAllBranches.sh
echo "Fetch branch: `cat checkoutAllBranches.sh`"
./checkoutAllBranches.sh
git checkout master
git remote rm origin
rm checkoutAllBranches.sh
for config_dir in `ls -a`; do
cp -r $config_dir $clonePath/;
done
echo "API Config update complete..."
Dockerfile which issues this script execution
ENTRYPOINT ["sh","config-update-force.sh","|| true"]
The error below causes the container startup failure despite setting the command status to 0 manually using || true
ERROR:
Error:
cp: cannot create regular file '/data/./.git/objects/pack/pack-27a9d...fb5e368e4cf.pack': Permission denied
cp: cannot create regular file '/data/./.git/objects/pack/pack-27a9d...fbae25e368e4cf.idx': Permission denied
I am looking for 2 options here:
Change these file permissions and then store them in the remote with rwx permissions
Do something to the docker file to ignore this script failure error and start the container.
DOCKERFILE:
FROM docker.hub.com/java11-temurin:latest
USER root
RUN apt-get update
RUN apt-get -y upgrade
RUN apt-get install -y rsync telnet vim wget git
RUN mkdir -p /opt/config/clone/data
RUN chown -R 1001:1001 /opt/config
USER 1001
ADD build/libs/my-api-config-server.jar .
ADD config-update-force.sh .
USER root
RUN chmod +x config-update-force.sh
USER 1001
EXPOSE 8080
CMD java $BASE_JAVA_OPTS $JAVA_OPTS -jar my-api-config-server.jar
ENTRYPOINT ["sh","config-update-force.sh","|| true"]
BASH SCRIPT:
#!/bin/bash
set +e
set +x
clonePath=/opt/clone/data/data
#source Optumfile.properties
echo "properties loaded: example ${git_host}"
if [ -d my-api-config ]; then
rm -rf my-api-config;
echo "existing my-api-config dir deleted..."
fi
git_url=https://github.com/my-api-config-server
git clone https://github.com/my-api-config-server
cd my-api-config-server
git branch -r | fgrep -v 'origin/HEAD' | sed 's| origin/|git checkout |' > checkoutAllBranches.sh
chmod +x checkoutAllBranches.sh
echo "Fetch branch: `cat checkoutAllBranches.sh`"
./checkoutAllBranches.sh
git checkout master
git remote rm origin
rm checkoutAllBranches.sh
for config_dir in `ls -a`; do
cp -r $config_dir $clonePath/;
done
echo "My API Config update complete..."
When you do in the script...
chmod +x checkoutAllBranches.sh
...than why not before cp
chmod -R +rwx ${clonePath}
...or if the stderr message 'wont impact anything'...
cp -r $config_dir $clonePath/ 2>/dev/null;
...even cp dont copy -verbosly.
?
When your Dockerfile declares an ENTRYPOINT, that command is the only thing the container does. If it also declares a CMD, the CMD is passed as additional arguments to the ENTRYPOINT; it is not run on its own unless the ENTRYPOINT makes sure to execute it.
Shell errors are not normally fatal, and especially if you explicitly set +e, even if a shell command fails the shell script will keep running. You see this in your output where you get multiple cp errors; the first error does not terminate the script.
You need to do two things here. The first is to set the ENTRYPOINT to actually run the CMD; the simplest and most common way to do this is to end the script with
exec "$#"
The second is to remove the || true from the Dockerfile. As you have it written out currently, this is passed as the first argument to the entrypoint wrapper – it is not run through a shell and it is not interpreted as a "or" operator. If your script begins with a "shebang" line and is marked executable (both of these are correct in the question) the you do not explicitly need the sh interpreter.
# must be a JSON array; no additional "|| true" argument; no sh -c wrapper
ENTRYPOINT ["./config-update-force.sh"]
# any valid CMD will work with `exec "$#"
CMD java $BASE_JAVA_OPTS $JAVA_OPTS -jar my-api-config-server.jar

Bash Script fails with error: OCI runtime exec failed

I am running the below script and getting error.
#!/bin/bash
webproxy=$(sudo docker ps -a --format "{{.Names}}"|grep webproxy)
webproxycheck="curl -k -s https://localhost:\${nginx_https_port}/HealthCheckService"
if [ -n "$webproxy" ] ; then
sudo docker exec $webproxy sh -c "$webproxycheck"
fi
Here is my docker ps -a output
$sudo docker ps -a --format "{{.Names}}"|grep webproxy
webproxy-dev-01
webproxy-dev2-01
when i run the command individually it works. For Example:
$sudo docker exec webproxy-dev-01 sh -c 'curl -k -s https://localhost:${nginx_https_port}/HealthCheckService'
HEALTHCHECK_OK
$sudo docker exec webproxy-dev2-01 sh -c 'curl -k -s https://localhost:${nginx_https_port}/HealthCheckService'
HEALTHCHECK_OK
Here is the error i get.
$ sh healthcheck.sh
OCI runtime exec failed: exec failed: container_linux.go:348: starting container process caused "exec: \"webproxy-dev-01\": executable file not found in $PATH": unknown
Could someone please help me with the error. Any help will be greatly appreciated.
Because the variable contains two tokens (on two separate lines) that's what the variable expands to. You are running
sudo docker exec webproxy-dev-01 webproxy-dev2-01 ...
which of course is an error.
It's not clear what you actually expect to happen, but if you want to loop over those values, that's
for host in $webproxy; do
sudo docker exec "$host" sh -c "$webproxycheck"
done
which will conveniently loop zero times if the variable is empty.
If you just want one value, maybe add head -n 1 to the pipe, or pass a more specific regular expression to grep so it only matches one container. (If you have control over these containers, probably run them with --name so you can unambiguously identify them.)
Based on your given script, you are trying to "exec" the following
sudo docker exec webproxy-dev2-01
webproxy-dev-01 sh -c "curl -k -s https://localhost:${nginx_https_port}/HealthCheckService"
As you see, here is your error.
sudo docker exec webproxy-dev2-01
webproxy-dev-01 [...]
The problem is this line:
webproxy=$(sudo docker ps -a --format "{{.Names}}"|grep webproxy)
which results in the following (you also posted this):
webproxy-dev2-01
webproxy-dev-01
Now, the issue is, that your docker exec command now takes both images names (coming from the variable assignment $webproxy), interpreting the second entry (which is webproxy-dev-01 and sepetrated by \n) as the exec command. This is now intperreted as the given command which is not valid and cannot been found: That's what the error tells you.
A workaround would be the following:
webproxy=$(sudo docker ps -a --format "{{.Names}}"| grep webproxy | head -n 1)
It only graps the first entry of your output. You can of course adapt this to do this in a loop.
A small snippet:
#!/bin/bash
webproxy=$(sudo docker ps -a --format "{{.Names}}"| grep webproxy )
echo ${webproxy}
webproxycheck="curl -k -s https://localhost:\${nginx_https_port}/HealthCheckService"
while IFS= read -r line; do
if [ -n "$line" ] ; then
echo "sudo docker exec ${line} sh -c \"${webproxycheck}\""
fi
done <<< "$webproxy"

creating a symbolic link inside a docker container from a docker host

I have a script on the docker host that i want to run and create symbolic links inside its containers. However, i cannot seem to get the symbolic link created when i run my script below:
#!/bin/bash
declare -A containers
while IFS== read -r key value; do
containers[$key]=${value}
S=$(sudo docker exec -t $key ln -s /srv/my.cnf /etc/mysql/my.cnf);
done < "/opt/containers.txt"
The weird thing is that when i run the command outside the script directly in the terminal, it actually works. E.g.,
sudo docker exec -t db-test-1 ln -s /srv/my.cnf /etc/mysql/my.cnf
So not sure why it won't run in the script. Any suggestions?
For testing, you can see if isolating the command (here ln) in its own shel helps:
S=$(sudo docker exec -t $key /bin/sh -c "ln -s /srv/my.cnf /etc/mysql/my.cnf");

unable to create docker container for tensorflow serving

I am trying to create a tensorflow serving docker container but I am getting the following error while running the docker create command
I am unable to figure out if its because of any location error or my /bin/bash file is broken. What can I do to fix this issue ? Thanks in advance.
What base image are you using for your container image? I checked busybox and alpine. They have ash by default but not bash. Once you create your image you can run it as follows:
docker run -it my-image-name "sh"
This should get you into an interactive shell. The cd into /bin and check which commands are available using ls.
I got this in alpine
/ # ls /bin
ash df getopt linux64 mpstat rev sync
base64 dmesg grep ln mv rm tar
bbconfig dnsdomainname gunzip login netstat rmdir touch
busybox dumpkmap gzip ls nice run-parts true
cat echo hostname lzop pidof sed umount
chgrp ed ionice makemime ping setpriv uname
chmod egrep iostat mkdir ping6 setserial usleep
chown false ipcalc mknod pipe_progress sh watch
conspy fatattr kbd_mode mktemp printenv sleep zcat
cp fdflush kill more ps stat
date fgrep link mount pwd stty
dd fsync linux32 mountpoint reformime su
A container is an instance created from a container-image. In your case your container tf_container_gpu has been created from the image you specified. You can give your container a name only the time you create it. After that you just need to start it with that name.
docker start tf_container_gpu should do.
if you want to recreate your container (say after you re-build your image) first remove the earlier container instance
docker container rm tf_container_gpu. Then run the container again
docker run --name=tf_container_gpu <image-name>
To just start and stop the container
docker start tf_container_gpu
docker stop tf_container_gpu

Exec sed command to a docker container

I'm trying to change a config file that is inside a docker container.
docker exec container_name sed -ire '/URL_BASE = /c\api.myapiurl' tmp/config.ini
Executing this sed command locally works just fine, but when I try to execute this in the container I receive the following error message.
sed: cannot rename tmp/config.ini: Operation not permitted
What I need to do is replace the 'URL_BASE =' from the 'config.ini' before deploy the container to my server.
I don't know why the sed command is trying to rename the file when its not suppose to.
Any ideas?
What I've tried
I tried to execute with the --privileged flag, but didn't worked. I tried to change the file permissions with chmod but I couldn't for the same reason of permission.
docker exec --privileged container_name sed -ire '/URL_BASE = /c\api.myapiurl' tmp/config.ini
Result: sed: cannot rename tmp/config.ini: Operation not permitted
Chmod
docker exec --privileged container_name chmod 755 tmp/config.ini
Result: chmod: changing permissions of 'tmp/config.ini': Operation not permitted
I also have tried execute with sudo before docker but didn't work either.
Nehal is absolutely right, sed works creating a local file so you just need a different approach, which is commonly used on Linux: heredocs.
Taking just the first lines from the documentation, a here document is a special-purpose code block. It uses a form of I/O redirection to feed a command list to an interactive program.
It can help us with docker exec as follows:
docker exec -i container_name bash <<EOF
sed -ire '/URL_BASE = /c\api.myapiurl' /tmp/config.ini
grep URL_BASE /tmp/config.ini
# any other command you like
EOF
Be aware of the -t, which is commonly used running bash, because it allocates a pseudo-TTY, and we don't really need that.
Also, to be safe always use absolute paths like /tmp/config.ini.
docker exec -i <container name> sed -i 's/xxx/${yyy}/g' path/filename.yaml
This is working for me.

Resources