Cannot execute ls command in docker - docker

I'm trying to use docker compose to run my services. But for some reason I'm not able to call e.g. this command 'ls -la /home'. It gives me an error:
Cannot start service test: failed to create shim task: OCI runtime create failed: runc >create failed: unable to start container process: exec: "ls /home": stat ls /home: no such >file or directory: unknown
whereas when I use just 'ls' then I see all the directories... what's wrong?
Below is my docker-compose file:
version: "3"
services:
mqtt_broker:
build:
dockerfile: Dockerfile
context: ./
network_mode: host
test:
depends_on: [ mqtt_broker ]
image: ubuntu:22.04
command:
- ls -la /home
network_mode: host

Enclose your command with the array notation (just like in Dockerfiles), so that it is properly joined together as one, instead of different parts being interpreted separately.
command: [ "ls", "-la", "/home" ]
To run multiple commands,
command: ["/bin/bash", "-c", "ls -lah; whoami; hostname"]
But as the comments pointed out, as this increases complexity, consider running a script instead.

There is no command "ls -la /home". There is command ls that takes -la argument and /home argument.
command:
- ls
- "-la"
- /home
Or alternatively, docker-compose will do the splitting if you pass a string instead of an array (consult YAML specification):
command: "ls -la /home"
Or just:
command: ls -la /home

It might be a missing $PATH problem -- does the following work?
command:
- /bin/ls -la /home

Related

why do i need tty: true in docker-compose.yml and other images do not?

I've been looking for the answer for a while, but I haven't found it and I need to understand before I go ahead with my tests.
I am creating an image based on Alpine by installing bash as in the following image:
FROM alpine:3.12
RUN apk add --no-cache --upgrade bash rsync gzip \
&& rm -rf /var/cache/apk/*
COPY ./docker/backup/hello.sh /hello.sh
RUN mkdir /backup \
&& chmod u+x /hello.sh
WORKDIR /backup
ENTRYPOINT ["sh","/hello.sh"]
CMD ["/bin/bash"]
hello.sh
#!/bin/sh
echo "=> Hello Word"
echo "$#"
exec "$#"
The first time I tried bash I could not access with the following command:
docker-compose exec myalpine bash
But searching if I found the answer, I had to put in my docker-compose.yml tty: true, and I already was able to access the myalpine container shell after launching the command docker-compose up -d
Resulting in a part of my docker-compose.yml as follows
services:
myalpine:
build:
context: ./
dockerfile: ./docker/backup/Dockerfile
args:
- DOCKER_ENV=${DOCKER_ENV}
restart: unless-stopped
tty: true
container_name: ${PROJECT_NAME}-files
volumes:
- appdata:/app
- ./data/app/backup:/backup
mysql:
build:
context: ./
dockerfile: ./docker/mysql/Dockerfile
args:
- MYSQL_VERSION=${MYSQL_VERSION}
- DOCKER_ENV=${DOCKER_ENV}
restart: always
container_name: ${PROJECT_NAME}-mysql
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
volumes:
- dbdata:/var/lib/mysql
networks:
- db
And now my question is why in other services of my docker-compose like mysql, I can access the bash without adding tty:true?
Example:
docker-compose exec mysql bash
I can access without having added tty:true to the docker-compose.yml, so there must be something in Alpine's image that I don't understand and would like to understand.
I had reproduced your example with a cut-down version of the dockerfile and the docker-compose.yaml, and after running docker-compose up. First I ran without a tty attached, so I have the following:
~$ docker-compose up
...
...
WARNING: Image for service myalpine was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Creating test-fies ... done
Attaching to test-fies
test-fies | => Hello Word
test-fies | /bin/bash
~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9a72817b0e28 tty_up_myalpine "sh /hello.sh /bin/b…" 5 minutes ago Restarting (0) Less than a second ago myalpine-fies
As you can see, the container is restarting all the time. Reason for this is that the hello.sh as an entrypoint will receive the command /bin/bash and will execute the bash. This will try to create an interactive shell but since there is no tty the creation of the shell fails and the container is stopped. Because the container is marked restart: unless-stopped it will be in a constant loop of restarting.
Since the container is not running, you are not able to execute docker-compose exec myalpine bash
Once you add a tty to the container, bash will be able to create interactive session and the container will be started.
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
745f5139f510 tty_up_myalpine "sh /hello.sh /bin/b…" 10 seconds ago Up 9 seconds myalpine-fies
Reason why this is not a case with mysql is that this image ends up initiating a daemon process which is a non-interactive process that is detached from a tty.

docker-compose: file shows up with ls but can't be found when executed

I want to run a shellscript for my docker-compose frontend container. When i try to run the file I get an error suggesting that the shell file can't be found:
services.app | /usr/local/bin/docker-entrypoint.sh: exec: line 8: /usr/src/app/frontend/entrypoint.sh: not found
This is my docker-compose file:
docker-compose entry:
frontend:
build: ./frontend
image: app
container_name: services.app
volumes:
- .:/usr/src/app
ports:
- "3000:3000"
env_file: ./.env
stdin_open: true
command: /usr/src/app/frontend/entrypoint.sh prod
However, when I run command: ls /usr/src/app/frontend/ in the docker-compose file I can see the file:
services.app | entrypoint.sh
Is the shell file really missing or am I misinterpreting this error? Any suggestions on how to fix it?
edit:
the entrypoint.sh script:
#!/bin/bash
cp -r /usr/src/cache/node_modules/. /usr/src/app/node_modules/
exec npm start
Well I can emulate the error, although I cannot say that's what's happening in your case:
$ mkdir /tmp/demo
$ ln -s /no/such/dir/entry.sh /tmp/demo/entry.sh # create soft link to non existent file
$ chmod +x /tmp/demo/entry.sh # and make it executable for good measure
$ ls /tmp/demo # so now we can list the file
entry.sh
$ /tmp/demo/entry.sh # but cannot execute it
-bash: /tmp/demo/entry.sh: No such file or directory
so what worked for me in the end was simply to append sh in front of the command:
command: sh /usr/src/app/frontend/entrypoint.sh prod

Why is Docker not binding my volumes to the container?

I have a very simple project:
Dockerfile:
from node:lts
VOLUME /scripts
WORKDIR /scripts
RUN bash -c 'ls /'
RUN bash -c 'ls /scripts'
RUN script.sh
docker-compose.yml:
version: '3.7'
services:
service:
build: .
volumes:
- .:/scripts
Then I run docker-compose build but it fails with /bin/sh: 1: script.sh: not found
From the ls /scripts I can see that Docker isn't binding my script to the container. I have Docker 19.03.8. Do you know what I am doing wrong?
When you run a Docker Compose file, the build: block is run first, and it ignores all of the options outside that block. A Dockerfile never has mounted volumes, it can never make network calls to other Compose containers, and it won't see environment: variables that are set elsewhere.
That means you must explicitly COPY code into your image before you can RUN it.
FROM node:ls
WORKDIR /scripts
COPY script.sh .
RUN ./script.sh

Mapping volume related with WORKDIR

How can I map a volume using the Image WORKDIR in docker-compose?
I'm trying to use
services:
my-app:
image: <image>
volumes:
- ./scripts:./scripts
But when I try to execute docker-compose up -d, I get the error bellow:
Cannot create container for service my-app: invalid volume spec "scripts": invalid volume specification: 'scripts': invalid mount config for type "volume": invalid mount path: 'scripts' mount path must be absolute
Is there any way to map my scripts folder in the WORKDIR of a image without knowing where is this folder?
No there is no way to do that by default as such. But you can use a workaround if you would like
services:
my-app:
image: <image>
volumes:
- ./scripts:/scripts
command: bash -c "ln -s /scripts scripts && orignal command"
But this will require you to know the command before hand. So either you know command before hand or the WORKDIR before hand.
You can also change working directory to any other directory you want. If you don't want to override the command then another possible option is below
docker-compose up -d
docker-compose exec my-app ln -s /scripts scripts

Running and configuring mqtt broker with docker composer

In the documentation of docker composer version 3, from what I understood, to run some commands after a container has started I need to add the "command" tag as follows:
version: "3"
services:
broker:
image: "toke/mosquitto"
restart: always
ports:
- "1883:1883"
- "9001:9001"
command: ["cd /etc/mosquitto", "echo \"\" > mosquitto.pwd", "mosquitto_passwd -b /etc/mosquitto/mosquitto.pwd user pass", "echo \"password_file mosquitto.pwd\" >> mosquitto.conf", "echo \"allow_anonymous false\" >> mosquitto.conf"]
The log returns /usr/bin/docker-entrypoint.sh: 5: exec: cd /etc/mosquitto: not found
A workaround could be specify in the composer file what dockerfile to run and add the commands that should run there, so I created one dockerfile:
FROM toke/mosquitto
WORKDIR .
EXPOSE 1883:1883 9001:9001
ENTRYPOINT cd /etc/mosquitto
ENTRYPOINT echo "" > mosquitto.pwd
ENTRYPOINT mosquitto_passwd -b mosquitto.pwd usertest passwordtest
ENTRYPOINT echo "password_file mosquitto.pwd" >> mosquitto.conf
ENTRYPOINT echo "allow_anonymous false" >> mosquitto.conf
The container's keep restarting and the log doesn't return anything. I've also tried changing the "ENTRYPOINT" for "CMD" with no changing in the output.
As an addend specifying the docker composer file to use a specific dockerfile it fails to parse and says:
ERROR: The Compose file '.\docker-compose.yml' is invalid because:
Unsupported config option for services.broker: 'dockerfile'
As in it can't parse or doesn't understand "dockerfile" tag. Does anyone know how to configure a dockerfile or even docker-composer to run the commands intended in this post to configure a mqtt broker?
The command entry in the compose file is not a list of commands to run, it's a single command and it's arguments
e.g. to run mosquitto -c /etc/mosquitto/mosquitto.conf
command: ["mosquitto", "-c", "/etc/mosquitto/mosquitto.conf"]
As for the Dockerfile, There should only be one ENTRYPOINT or CMD. If you want to run multiple commands then you should create a shell script to do run them, add it to the container then use ENTRYPOINT or CMD to run the script.

Resources