Permission denied when trying to copy files from docker container to host - docker

I am trying to follow this question as a guide for how to copy a file from a docker container back to the host however I am getting a permission denied error as can be seen in the following copy of my terminal:
mdbl#mdblLXPS:~/Documents/research/docker/copying$ ls -ltr
total 12
-rw-rw-r-- 1 mdbl mdbl 28 Jan 2 23:26 Dockerfile
-rw-rw-r-- 1 mdbl mdbl 368 Jan 2 23:52 script.sh
-rwxrwxrwx 1 mdbl mdbl 15 Jan 3 00:16 test.txt
mdbl#mdblLXPS:~/Documents/research/docker/copying$ cat Dockerfile
FROM alpine
COPY test.txt .
mdbl#mdblLXPS:~/Documents/research/docker/copying$ cat test.txt
this is a test
mdbl#mdblLXPS:~/Documents/research/docker/copying$ cat script.sh
echo create the image
sudo docker build -t testimg .
echo
echo list the newly created image
sudo docker images | head -2
echo
echo create the container
sudo docker container create --name mycont testimg
echo
echo list the newly created container
sudo docker container ls -a | head -2
echo
echo try copying test.txt from the container
sudo docker cp mycont:/test.txt .
mdbl#mdblLXPS:~/Documents/research/docker/copying$ source script.sh
create the image
Sending build context to Docker daemon 4.096kB
Step 1/2 : FROM alpine
---> 49176f190c7e
Step 2/2 : COPY test.txt .
---> 70b40a27f26d
Successfully built 70b40a27f26d
Successfully tagged testimg:latest
list the newly created image
REPOSITORY TAG IMAGE ID CREATED SIZE
testimg latest 70b40a27f26d Less than a second ago 7.05MB
create the container
9c9396df4ab3e0538eb1aa995f13852d5328fbaa5597c82b731bb177cf809068
list the newly created container
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9c9396df4ab3 testimg "/bin/sh" Less than a second ago Created mycont
try copying test.txt from the container
unlinkat /home/mdbl/Documents/research/docker/copying/test.txt: permission denied
I create a docker image from an alpine base image that contains a test file test.txt. Then I create a container from this image and try to copy this file back to the host, however I get the error unlinkat /home/mdbl/Documents/research/docker/copying/test.txt: permission denied. This is despite the fact that test.txt has full permissions associated to it as can be seen by the ls -ltr command. Why is this and how can I resolve this error?

Related

Couldn't connect to Docker daemon at http+docker://localhost - is it running? (special use case)

I guess you all know this error pretty good. In order to understand why I may encouter it, you may need some background info about the context as it's not really a common use (i think at least).
I have an UNRAID server
A VM running in this server
A bunch of services running in containers via compose in this VM (referenced later as my production VM)
[PROBLEM] I need to add a container that itself will run compose from this official image
This last container is maintained by myself and should run an API, web client, db, ect. When building it I first trigger the build of proxy, api, web and other project that I develop and once ot's done I build the compose one from the images I just built and some open source ones.
To test I created a dummy VM on my unraid server and created a compose environment similar to my production VM. (let's call it my test VM). I added a compose file with only my app and portainer.
The problem is when I run 'docker-compose up' on that test server, portainer start but my app fails because it cannot connect to it's docker daemon (see logs below)
What I tried:
running my app as root or a created user
adding the created user to docker group (but docker group does not exists so I'm creating it; seems odd to me...)
checking permission on /var/run/docker.sock: it returned a file not found error even as root
passing the socket from my test VM when running the parent compose via a volume (- "/var/run/docker.sock:/var/run/docker.sock")
Dockerfile:
FROM docker/compose
# Create plaxdmin user
RUN adduser plaxdmin --disabled-password
RUN addgroup docker
RUN addgroup plaxdmin docker
USER plaxdmin
# Final values
ARG PLAXDMIN_VERSION
ARG RELEASE_TYPE
ENV PLAXDMIN_VERSION=$PLAXDMIN_VERSION
ENV RELEASE_TYPE=$RELEASE_TYPE
# Default user defined values
ENV TIMEZONE=Europe/Paris
ENV PLAXDMIN_DNS="plaxdmin.default.org"
# Init folders and copy docker-compose api configuration files
WORKDIR /var/log/plaxdmin
WORKDIR /etc/plaxdmin
ADD ./resources/conf/* ./
WORKDIR /opt/plaxdmin/
ADD ./resources/docker-compose.yml ./
# Expose port
EXPOSE 80
# On run debug and start compose fleet
CMD docker -v \
&& docker-compose -v \
&& printenv \
&& ls -al /etc/plaxdmin \
&& ls -al /opt/plaxdmin/ \
&& ls -al /var/log/plaxdmin/ \
&& pwd \
&& whoami \
&& groups $user \
# && ls -la /var/run/docker.sock \
&& docker-compose up || true
docker build logs:
Step 1/18 : FROM docker/compose
latest: Pulling from docker/compose
aad63a933944: Pulling fs layer
b396cd7cbac4: Pulling fs layer
0426ec0ed60a: Pulling fs layer
9ac2a98ece5b: Pulling fs layer
9ac2a98ece5b: Waiting
b396cd7cbac4: Verifying Checksum
b396cd7cbac4: Download complete
aad63a933944: Verifying Checksum
aad63a933944: Download complete
aad63a933944: Pull complete
0426ec0ed60a: Verifying Checksum
0426ec0ed60a: Download complete
b396cd7cbac4: Pull complete
9ac2a98ece5b: Verifying Checksum
9ac2a98ece5b: Download complete
0426ec0ed60a: Pull complete
9ac2a98ece5b: Pull complete
Digest: sha256:b60a020c0f68047b353a4a747f27f5e5ddb17116b7b018762edfb6f7a6439a82
Status: Downloaded newer image for docker/compose:latest
---> c3e188a6b38f
Step 2/18 : RUN adduser plaxdmin --disabled-password
---> Running in 07aa9a297234
Removing intermediate container 07aa9a297234
---> 494c8a4291e0
Step 3/18 : RUN addgroup docker
---> Running in f64e5022e65d
Removing intermediate container f64e5022e65d
---> 84ee5fbf6dea
Step 4/18 : RUN addgroup plaxdmin docker
---> Running in 0efa66b73f4a
Removing intermediate container 0efa66b73f4a
---> eb647c03c118
Step 5/18 : USER plaxdmin
---> Running in 4529203341d1
Removing intermediate container 4529203341d1
---> 8501d9993307
Step 6/18 : ARG PLAXDMIN_VERSION
---> Running in 07d61186fadd
Removing intermediate container 07d61186fadd
---> ed6e9f9df0ab
Step 7/18 : ARG RELEASE_TYPE
---> Running in 0fa98c641843
Removing intermediate container 0fa98c641843
---> d0fe2f700e53
Step 8/18 : ENV TIMEZONE=Europe/Paris
---> Running in 5c5d383c6858
Removing intermediate container 5c5d383c6858
---> 48394a4e01b3
Step 9/18 : ENV PLAXDMIN_DNS="plaxdmin.default.org"
---> Running in 187304a8a1ed
Removing intermediate container 187304a8a1ed
---> 5827abebd0ff
Step 10/18 : ENV PLAXDMIN_VERSION=$PLAXDMIN_VERSION
---> Running in 54ff13db32e6
Removing intermediate container 54ff13db32e6
---> 9377ac82544e
Step 11/18 : ENV RELEASE_TYPE=$RELEASE_TYPE
---> Running in 2da68d0375ac
Removing intermediate container 2da68d0375ac
---> dd09ee57c867
Step 12/18 : WORKDIR /var/log/plaxdmin
---> Running in 9ac2fdb93c5e
Removing intermediate container 9ac2fdb93c5e
---> 252771ee5ff4
Step 13/18 : WORKDIR /etc/plaxdmin
---> Running in eb6c9a16b12f
Removing intermediate container eb6c9a16b12f
---> 6fd180adcb80
Step 14/18 : ADD ./resources/conf/* ./
---> 70e10c126b4f
Step 15/18 : WORKDIR /opt/plaxdmin/
---> Running in 0a6f15afc915
Removing intermediate container 0a6f15afc915
---> d8c321d31689
Step 16/18 : ADD ./resources/docker-compose.yml ./
---> 60847c38d0be
Step 17/18 : EXPOSE 80
---> Running in cbe2a4d7f8be
Removing intermediate container cbe2a4d7f8be
---> 56269d51e6d5
Step 18/18 : CMD docker -v && docker-compose -v && printenv && ls -al /etc/plaxdmin && ls -al /opt/plaxdmin/ && ls -al /var/log/plaxdmin/ && pwd && whoami && groups $user && docker-compose up || true
---> Running in 49d1a3505198
Removing intermediate container 49d1a3505198
---> beba0e2fd039
Successfully built beba0e2fd039
Successfully tagged plaxdmin/full:latest
Successfully tagged plaxdmin/full:unstable
Successfully tagged plaxdmin/full:v-202102010319
Successfully tagged plaxdmin/full:64ce4f02f88ac81219dd61ae0d8c2e4aa6e0403e
Successfully tagged plaxdmin/full:master
Start logs:
plaxdmin_1 | Docker version 19.03.8, build afacb8b7f0
plaxdmin_1 | docker-compose version 1.26.2, build eefe0d3
plaxdmin_1 | HOSTNAME=b3a358707bd6
plaxdmin_1 | SHLVL=2
plaxdmin_1 | HOME=/home/plaxdmin
plaxdmin_1 | PGID=1421
plaxdmin_1 | TIMEZONE=Europe/Paris
plaxdmin_1 | RELEASE_TYPE=unstable
plaxdmin_1 | PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
plaxdmin_1 | PLAXDMIN_DNS=plaxdmin.vba.ovh
plaxdmin_1 | PUID=1421
plaxdmin_1 | PWD=/opt/plaxdmin
plaxdmin_1 | PLAXDMIN_VERSION=v-202102010319
plaxdmin_1 | total 20
plaxdmin_1 | drwxr-xr-x 1 root root 4096 Feb 1 15:57 .
plaxdmin_1 | drwxr-xr-x 1 root root 4096 Feb 1 15:59 ..
plaxdmin_1 | -rw-rw-rw- 1 root root 262 Jan 31 02:06 application.properties
plaxdmin_1 | -rw-rw-rw- 1 root root 690 Jan 31 02:06 log4j.properties
plaxdmin_1 | -rw-rw-rw- 1 root root 1518 Jan 31 19:31 nginx.conf
plaxdmin_1 | total 12
plaxdmin_1 | drwxr-xr-x 1 root root 4096 Feb 1 15:57 .
plaxdmin_1 | drwxr-xr-x 1 root root 4096 Feb 1 15:57 ..
plaxdmin_1 | -rw-rw-rw- 1 root root 2374 Feb 1 02:01 docker-compose.yml
plaxdmin_1 | total 8
plaxdmin_1 | drwxr-xr-x 2 root root 4096 Feb 1 15:57 .
plaxdmin_1 | drwxr-xr-x 1 root root 4096 Feb 1 15:57 ..
plaxdmin_1 | /opt/plaxdmin
plaxdmin_1 | plaxdmin
plaxdmin_1 | plaxdmin docker
plaxdmin_1 | Couldn't connect to Docker daemon at http+docker://localhost - is it running?
plaxdmin_1 |
plaxdmin_1 | If it's at a non-standard location, specify the URL with the DOCKER_HOST environment variable.
Since the goal of your container is to run Docker commands, it has permissions to take over the entire host system should it choose to. It's not any less safe to run it as USER root, which will also address the socket permission problem. Since your Dockerfile doesn't actually do anything switched to the alternate user (COPY makes files be owned by root by default and you do not RUN any commands) you can also delete the USER line and the alternate-user setup.
# This user and group will not be used; delete these lines
# RUN adduser plaxdmin --disabled-password
# RUN addgroup docker
# RUN addgroup plaxdmin docker
# Nothing is done as this user
# Stay as the default root user to be able to run `docker` commands
# USER plaxdmin
If the host's /var/run/docker.sock is mode 0660 and owned by a group docker (a typical setup) the container process must run as the same numeric group ID in order to be able to access the socket. This will intrinsically be host-specific and it's not something you can set in your Dockerfile.
When you launch the orchestration container, you can run it with an additional group to put it in the docker group
# If the container process isn't already running as root
docker run \
-v /var/run/docker.sock:/var/run/docker.sock \
--group-add docker \
...
Or, in Compose version 2 syntax (but not version 3) there is a group_add: option that can specify this
version: '2.4'
services:
orchestrator:
volumes:
- /var/run/docker.sock:/var/run/docker.sock
group_add:
- docker
(The documentation says the group must exist in both contexts, so you may need to look up the numeric group ID and use that instead.)

docker ADD --chown bug or feature?

I am having a problem adding a file to an image and setting ownership via --chown flag. Specifically, here is a dockerfile adding a simple text file:
FROM fedora:24
ARG user_name=slave
ARG user_uid=1000
ARG user_home=/home/$user_name/
RUN useradd -l -u ${user_uid} -ms /bin/bash $user_name
WORKDIR ${user_home}
USER ${user_name}
ADD --chown=1397765041:1397765041 test.txt ./
CMD ls -l
This results in expected ownership of text.txt as can be seen:
$ docker run --rm -it bm/tmp:latest
total 4
-rw-r--r-- 1 some_user 1397765041 6 Oct 21 20:00 test.txt
Cool. Now if I change test.txt to a tar file (for example boost_1_57_0.tar.bz2), and rebuild, this is what I get:
$ docker run --rm -it bm/tmp:latest
total 4
drwx------ 8 501 root 4096 Oct 31 2014 boost_1_57_0
Here is how I am building (probably doesn't matter tho):
docker build -t bm/tmp --build-arg user_name=some_user --build-arg user_uid=1397765041 .
As we can see, ownership is NOT as expected in this case. It seems the behavior of --chown differs from the two cases shown above. I know that ADD automatically extracts tars. I don't know how the ownership is being set in the case where the file is a tar file. Anyone?
Unfortunately, ADD --chown only works for regular files. ADD with a tarball uses the ownership and permissions listed inside in tarball.
Workarounds:
Run tar yourself with --owner/--owner-map/--group/--group-map.
chown -R after the ADD.

How do i give a non root user access to docker when using docker-dind?

I'm trying to run a Go CD agent using docker-dind to auto build some of my docker images.
I'm having trouble getting the user go to have access to the docker daemon.
When I try and access docker info I get the following:
[go] Task: /bin/sh ./builder.shtook: 2.820s
[START]
[USER] go
[TAG] manual
Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.32/containers/fish/angular-cli/json: dial unix /var/run/docker.sock: connect: permission denied
Sending build context to Docker daemon 3.072kB
Step 1/8 : FROM node:8-alpine
---> 4db2697ce114
Step 2/8 : MAINTAINER jack#fish.com
---> Using cache
---> 22f46bf6b4c1
Step 3/8 : VOLUME /usr/local/share/.cache/yarn/v1
---> Using cache
---> 86b979e7a2b4
Step 4/8 : RUN apk add --no-cache --update build-base python
---> Using cache
---> 4a08b0a1fc9d
Step 5/8 : RUN yarn global add #angular/cli#1.5.3
---> Using cache
---> 6fe4530181a5
Step 6/8 : EXPOSE 4200
---> Using cache
---> 480edc47696e
Step 7/8 : COPY ./docker-entrypoint.sh /
---> Using cache
---> 329f9eaa5c76
Step 8/8 : ENTRYPOINT /docker-entrypoint.sh
---> Using cache
---> cb1180ff8e9f
Successfully built cb1180ff8e9f
Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.32/containers/fish/angular-cli/json: dial unix /var/run/docker.sock: connect: permission denied
My root user can accesss docker info properly, but the go user fails.
$ cat /etc/group
root:x:0:root
bin:x:1:root,bin,daemon
daemon:x:2:root,bin,daemon
sys:x:3:root,bin,adm
....
adm:x:4:root,adm,daemon
wheel:x:10:root
xfs:x:33:xfs
ping:x:999:
nogroup:x:65533:
nobody:x:65534:
dockremap:x:101:dockremap,go
go:x:1000:go
My docker.sock permissions are as follows:
$ ls -alh /var/run/docker.sock
srw-rw---- 1 root 993 0 Apr 20 2017 /var/run/docker.sock
What do I need to append to my Dockerfile in order to allow the go user to access the docker daemon?
When running a dind container, IE docker in docker, it its common place to volume mount /var/run/docker.sock:/var/run/docker.sock from the host into the dind-container.
When this occurs, the PID is not only owned by root, but by a numeric group id from the host.
Running the following inside the container should show you the host GID:
$ ls -alh /var/run/docker.sock
srw-rw---- 1 root 993 0 Apr 20 2017 /var/run/docker.sock
The above process is owned by group 993, 993 is derived from the host machines /etc/group -> docker role.
As it is nearly impossible to ensure that we have a common group id when the image is first built, the group id should be assigned at runtime using your docker-entrypoint.sh file.
My personal goal is to get this runtime user of 'go' for a GO CD go-agent, but one could substitute this approach for jenkins or any other runtime user.
As the dind & go-agent are both based off alpine linux, the following will work for alpine-linux:
#setup docker group based on hosts mount gid
echo "Adding hosts GID to docker system group"
# this only works if the docker group does not already exist
DOCKER_SOCKET=/var/run/docker.sock
DOCKER_GROUP=docker
BUILD_USER=go
if [ -S ${DOCKER_SOCKET} ]; then
DOCKER_GID=$(stat -c '%g' ${DOCKER_SOCKET})
#addgroup is distribution specific
addgroup -S -g ${DOCKER_GID} ${DOCKER_GROUP}
addgroup ${BUILD_USER} ${DOCKER_GROUP}
fi
If you exec into the container, and cat your /etc/group file, you should see the following:
docker:x:993:go
This is a slightly modified version of #Jack's answer.
I created a docker-entrypoint.sh which will determine the GID and reuse the group if it already exists. Primarily on Docker for Windows machines the Docker socket is using root. This would need runuser as su will only work if the user's shell is not set to nologin which in my case is set to nologin
#!/bin/sh
set -e
DOCKER_SOCKET=/var/run/docker.sock
RUNUSER=jobberuser
if [ -S ${DOCKER_SOCKET} ]; then
DOCKER_GID=$(stat -c '%g' ${DOCKER_SOCKET})
DOCKER_GROUP=$(getent group ${DOCKER_GID} | awk -F ":" '{ print $1 }')
if [ $DOCKER_GROUP ]
then
addgroup $RUNUSER $DOCKER_GROUP
else
addgroup -S -g ${DOCKER_GID} docker
addgroup $RUNUSER docker
fi
fi
exec runuser -u $RUNUSER -- $#
In order to allow other users to access Docker you need to:
sudo groupadd docker
sudo usermod -aG docker go
If you are running this command as the go user, you need to logout and login after performing above task.

File ownership after docker cp

How can I control which user owns the files I copy in and out of a container?
The docker cp command says this about file ownership:
The cp command behaves like the Unix cp -a command in that directories are copied recursively with permissions preserved if possible. Ownership is set to the user and primary group at the destination. For example, files copied to a container are created with UID:GID of the root user. Files copied to the local machine are created with the UID:GID of the user which invoked the docker cp command. However, if you specify the -a option, docker cp sets the ownership to the user and primary group at the source.
It says that files copied to a container are created as the root user, but that's not what I see. I create two files owned by user id 1005 and 1006. Those owners are translated into the container's user namespace. The -a option seems to make no difference when I copy the file into a container.
$ sudo chown 1005:1005 test.txt
$ ls -l test.txt
-rw-r--r-- 1 1005 1005 29 Oct 6 12:43 test.txt
$ docker volume create sandbox1
sandbox1
$ docker run --name run1 -vsandbox1:/data alpine echo OK
OK
$ docker cp test.txt run1:/data/test1005.txt
$ docker cp -a test.txt run1:/data/test1005a.txt
$ sudo chown 1006:1006 test.txt
$ docker cp test.txt run1:/data/test1006.txt
$ docker cp -a test.txt run1:/data/test1006a.txt
$ docker run --rm -vsandbox1:/data alpine ls -l /data
total 16
-rw-r--r-- 1 1005 1005 29 Oct 6 19:43 test1005.txt
-rw-r--r-- 1 1005 1005 29 Oct 6 19:43 test1005a.txt
-rw-r--r-- 1 1006 1006 29 Oct 6 19:43 test1006.txt
-rw-r--r-- 1 1006 1006 29 Oct 6 19:43 test1006a.txt
When I copy files out of the container, they are always owned by me. Again, the -a option seems to do nothing.
$ docker run --rm -vsandbox1:/data alpine cp /data/test1006.txt /data/test1007.txt
$ docker run --rm -vsandbox1:/data alpine chown 1007:1007 /data/test1007.txt
$ docker cp run1:/data/test1006.txt .
$ docker cp run1:/data/test1007.txt .
$ docker cp -a run1:/data/test1006.txt test1006a.txt
$ docker cp -a run1:/data/test1007.txt test1007a.txt
$ ls -l test*.txt
-rw-r--r-- 1 don don 29 Oct 6 12:43 test1006a.txt
-rw-r--r-- 1 don don 29 Oct 6 12:43 test1006.txt
-rw-r--r-- 1 don don 29 Oct 6 12:47 test1007a.txt
-rw-r--r-- 1 don don 29 Oct 6 12:47 test1007.txt
-rw-r--r-- 1 1006 1006 29 Oct 6 12:43 test.txt
$
You can also change the ownership by logging in as root user into the container :
docker exec -it --user root <container-id> /bin/bash
chown -R <username>:<groupname> <folder/file>
In addition to #Don Kirkby's answer, let me provide a similar example in bash/shell script for the case that you want to copy something into a container while applying different ownership and permissions than those of the original file.
Let's create a new container from a small image that will keep running by itself:
docker run -d --name nginx nginx:alpine
Now wel'll create a new file which is owned by the current user and has default permissions:
touch foo.bar
ls -ahl foo.bar
>> -rw-rw-r-- 1 my-user my-group 0 Sep 21 16:45 foo.bar
Copying this file into the container will set ownership and group to the UID of my user and preserve the permissions:
docker cp foo.bar nginx:/foo.bar
docker exec nginx sh -c 'ls -ahl /foo.bar'
>> -rw-rw-r-- 1 4098 4098 0 Sep 21 14:45 /foo.bar
Using a little tar work-around, however, I can change the ownership and permissions that are applied inside of the container.
tar -cf - foo.bar --mode u=+r,g=-rwx,o=-rwx --owner root --group root | docker cp - nginx:/
docker exec nginx sh -c 'ls -ahl /foo.bar'
>> -r-------- 1 root root 0 Sep 21 14:45 /foo.bar
tar options explained:
c creates a new archive instead of unpacking one.
f - will write to stdout instead of a file.
foo.bar is the input file to be packed.
--mode specifies the permissions for the target. Similar to chown, they can be given in symbolic notation or as an octal number.
--owner sets the new owner of the file.
--group sets the new group of the file.
docker cp - reads the file that is to be copied into the container from stdin.
This approach is useful when a file needs to be copied into a created container before it starts, such that docker exec is not an option (which can only operate on running containers).
Just a one-liner (similar to #ramu's answer), using root to make the call:
docker exec -u 0 -it <container-id> chown node:node /home/node/myfile
In order to get complete control of file ownership, I used the tar stream feature of docker cp:
If - is specified for either the SRC_PATH or DEST_PATH, you can also stream a tar archive from STDIN or to STDOUT.
I launch the docker cp process, then stream a tar file to or from the process. As the tar entries go past, I can adjust the ownership and permissions however I like.
Here's a simple example in Python that copies all the files from /outputs in the sandbox1 container to the current directory, excludes the current directory so its permissions don't get changed, and forces all the files to have read/write permissions for the user.
from subprocess import Popen, PIPE, CalledProcessError
import tarfile
def main():
export_args = ['sudo', 'docker', 'cp', 'sandbox1:/outputs/.', '-']
exporter = Popen(export_args, stdout=PIPE)
tar_file = tarfile.open(fileobj=exporter.stdout, mode='r|')
tar_file.extractall('.', members=exclude_root(tar_file))
exporter.wait()
if exporter.returncode:
raise CalledProcessError(exporter.returncode, export_args)
def exclude_root(tarinfos):
print('\nOutputs:')
for tarinfo in tarinfos:
if tarinfo.name != '.':
assert tarinfo.name.startswith('./'), tarinfo.name
print(tarinfo.name[2:])
tarinfo.mode |= 0o600
yield tarinfo
main()

Docker Jboss/wildfly: How to add datasources and MySQL connector

I am learning Docker which is completely new to me. I already was able to create an jboss/wildfly image, and then i was able to start jboss with my application using this Dockerfile:
FROM jboss/wildfly
CMD ["/opt/jboss/wildfly/bin/standalone.sh", "-c", "standalone-full.xml", "-b", "0.0.0.0"]
ADD mywebapp-web/target/mywebapp-1.0.war /opt/jboss/wildfly/standalone/deployments/mywebapp-1.0.war
Now i would like to add support for a MySQL Database by adding a datasource to the standalone and the mysql connector. For that i am following this example:
https://github.com/arun-gupta/docker-images/tree/master/wildfly-mysql-javaee7
Following is my dockerfile and my execute.sh script
Dockerfile:
FROM jboss/wildfly:latest
ADD customization /opt/jboss/wildfly/customization/
CMD ["/opt/jboss/wildfly/customization/execute.sh"]
execute script code:
#!/bin/bash
# Usage: execute.sh [WildFly mode] [configuration file]
#
# The default mode is 'standalone' and default configuration is based on the
# mode. It can be 'standalone.xml' or 'domain.xml'.
echo "=> Executing Customization script"
JBOSS_HOME=/opt/jboss/wildfly
JBOSS_CLI=$JBOSS_HOME/bin/jboss-cli.sh
JBOSS_MODE=${1:-"standalone"}
JBOSS_CONFIG=${2:-"$JBOSS_MODE.xml"}
function wait_for_server() {
until `$JBOSS_CLI -c ":read-attribute(name=server-state)" 2> /dev/null | grep -q running`; do
sleep 1
done
}
echo "=> Starting WildFly server"
echo "JBOSS_HOME : " $JBOSS_HOME
echo "JBOSS_CLI : " $JBOSS_CLI
echo "JBOSS_MODE : " $JBOSS_MODE
echo "JBOSS_CONFIG: " $JBOSS_CONFIG
echo $JBOSS_HOME/bin/$JBOSS_MODE.sh -b 0.0.0.0 -c $JBOSS_CONFIG &
$JBOSS_HOME/bin/$JBOSS_MODE.sh -b 0.0.0.0 -c $JBOSS_CONFIG &
echo "=> Waiting for the server to boot"
wait_for_server
echo "=> Executing the commands"
$JBOSS_CLI -c --file=`dirname "$0"`/commands.cli
# Add MySQL module
module add --name=com.mysql --resources=/opt/jboss/wildfly/customization/mysql-connector-java-5.1.39-bin.jar --dependencies=javax.api,javax.transaction.api
# Add MySQL driver
/subsystem=datasources/jdbc-driver=mysql:add(driver-name=mysql,driver-module-name=com.mysql,driver-xa-datasource-class-name=com.mysql.jdbc.jdbc2.optional.MysqlXADataSource)
# Deploy the WAR
#cp /opt/jboss/wildfly/customization/leadservice-1.0.war $JBOSS_HOME/$JBOSS_MODE/deployments/leadservice-1.0.war
echo "=> Shutting down WildFly"
if [ "$JBOSS_MODE" = "standalone" ]; then
$JBOSS_CLI -c ":shutdown"
else
$JBOSS_CLI -c "/host=*:shutdown"
fi
echo "=> Restarting WildFly"
$JBOSS_HOME/bin/$JBOSS_MODE.sh -b 0.0.0.0 -c $JBOSS_CONFIG
But I get a error when i run the image complaining that a file or directory is not found:
Building Image
$ docker build -t mpssantos/leadservice:latest .
Sending build context to Docker daemon 19.37 MB
Step 1 : FROM jboss/wildfly:latest
---> b8279b641e82
Step 2 : ADD customization /opt/jboss/wildfly/customization/
---> aea03d4f2819
Removing intermediate container 0920e2cd97fd
Step 3 : CMD /opt/jboss/wildfly/customization/execute.sh
---> Running in 8a0dbcb01855
---> 10335320b89d
Removing intermediate container 8a0dbcb01855
Successfully built 10335320b89d
SECURITY WARNING: You are building a Docker image from Windows against a non-Windows Docker host. All files and directories added to build context will have '-rwxr-xr-x' permissions. It is recommended to double check and reset permissions for sensitive files and directories.
Running image
$ docker run mpssantos/leadservice
no such file or directory
Error response from daemon: Cannot start container 5d3357ba17afa36e81d8794f2b0cd45cc00dde955b2b2054282c4ef17dd4f265: [8] System error: no such file or directory
Can someone let me know how can i access the filesystem so i can check which file or directory is complaining? Is there a better way to debug this?
I believe that is something related with the bash which is referred on first line of the script because the following echo is not printed
Thank you so much
I made it to ssh the container to check whats inside.
1) ssh to the docker machine: docker-machine ssh default
2) checked the container id with the command: docker ps -a
3) ssh to the container with the command: sudo docker exec -i -t 665b4a1e17b6 /bin/bash
4) i can check that the "/opt/jboss/wildfly/customization/" directory exists with the expected files
The customization dir have the following permissions and is listed like this:
drwxr-xr-x 2 root root 4096 Jun 12 23:44 customization
drwxr-xr-x 10 jboss jboss 4096 Jun 14 00:15 standalone
and the files inside the customization dir
drwxr-xr-x 2 root root 4096 Jun 12 23:44 .
drwxr-xr-x 12 jboss jboss 4096 Jun 14 00:15 ..
-rwxr-xr-x 1 root root 1755 Jun 12 20:06 execute.sh
-rwxr-xr-x 1 root root 989497 May 4 11:11 mysql-connector-java-5.1.39-bin.jar
if i try to execute the file i get this error
[jboss#d68190e4f0d8 customization]$ ./execute.sh
bash: ./execute.sh: /bin/bash^M: bad interpreter: No such file or directory
Does this bring light to anything?
Thank you so much again
I found the issue. The execute.sh file was with windows eof. I converted to UNIX And start to work.
I believe the execute.sh is not found. You can verify by running the following and finding the result is an empty directory:
docker run mpssantos/leadservice ls -al /opt/jboss/wildfly/customization/
The reason for this is you are doing your build on a different (virtual) machine than your local system, so it's pulling the "customization" folder from that VM. I'd run the build within the VM and place the files you want to import on that VM where the build can find it.

Resources