I have a simple docker-compose definition where I want to run a simple cmd/bash command:
basictests:
image: ${DOCKER_REGISTRY-}mytests
build:
context: .
dockerfile: MyTests/Dockerfile
container_name: "mytestscontainer"
command:
- echo "test"
depends_on:
dependent_env:
condition: service_healthy
note: It's a simplified test. Instead of calling echo, I actually want to run some more complicated scripts.
However, when I run this configuration, it throws with the following error:
==> /dev/null <==
tail: cannot open 'echo "test"' for reading: No such file or directory
Not sure where tail has come from and how it can be fixed. Looking at this, it should work. If I remove command, it works fine. Any help will be appriciated.
UPDATE: DockerFile doesn't do anything other than installing dotnet and building my library.
UPDATE2: The base docker file is:
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
# restore
COPY ["MyTests/MyTests.csproj", "MyTests/"]
RUN dotnet restore "MyTests/MyTests.csproj"
# build
COPY . .
WORKDIR "/src/MyTests"
RUN dotnet build "MyTests.csproj" -c Release -o /app/build
Adding suggested ENTRYPOINT ["/bin/bash", "-c"] to the end of above docker file doesn't help.
note: I'm novice in docker and docker-compose.
UPDATE3:
Adding ENTRYPOINT ["tail", "-f", "/dev/null"] to the end of docketfile and changing how I call command to command: [echo, test], doesn't help. In general, I'm curious what's the deal with tail? Why it appears in this case at all?
NOTE: for the context, I want to configure integration test that will work with few containers, so instead of echo .., I want to run dotnet test .. for my integration tests
UPDATE4: The below configuration:
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
EXPOSE 80
EXPOSE 443
# restore
COPY ["MyTests/MyTests.csproj", "MyTests/"]
RUN dotnet restore "MyTests/MyTests.csproj"
# build
COPY . .
WORKDIR "/src/MyTests"
RUN dotnet build "MyTests.csproj" -c Release -o /app/build
ENTRYPOINT ["/bin/bash"]
works well if I run it from cmd locally:
%SomePath%\Demo>docker build -f MyTests/Dockerfile -t mytest .
[+] Building 0.3s (12/12) FINISHED
=> [internal] load build definition from Dockerfile
=> => transferring dockerfile: 32B
=> [internal] load .dockerignore
=> => transferring context: 35B
=> [internal] load metadata for mcr.microsoft.com/dotnet/sdk:6.0
=> [1/7] FROM mcr.microsoft.com/dotnet/sdk:6.0
=> [internal] load build context
=> => transferring context: 2.00kB
=> CACHED [2/7] WORKDIR /src
=> CACHED [3/7] COPY [MyTests/MyTests.csproj, MyTests/]
=> CACHED [4/7] RUN dotnet restore "MyTests/MyTests.csproj"
=> CACHED [5/7] COPY . .
=> CACHED [6/7] WORKDIR /src/MyTests
=> CACHED [7/7] RUN dotnet build "MyTests.csproj" -c Release -o /app/build
=> exporting to image
=> => exporting layers
=> => writing image sha256:9c...
=> => naming to docker.io/library/mytest
%SomePath%\Demo>docker run -it mytest
root@999afef78716:/src/MyTests# ls
MyTests.csproj ApiTests.cs Properties obj
So, it looks like the problem is only about how to call it correctly from docker-compose configuration. I've also tried setting the below options
..
image: ${DOCKER_REGISTRY-}mytests
stdin_open: true # docker run -i
tty: true # docker run -t
..
with no luck.
UPDATE5: I've tried to simplify all logic I have to these 2 files with new console application:
Dockerfile:
FROM alpine:3.14
WORKDIR "/src"
CMD ["/bin/bash"]
# same behavior if I use `CMD ["/bin/sh"]`
docker-compose:
version: '3.4'
services:
consoleappdocker:
image: ${DOCKER_REGISTRY-}consoleappdocker
build:
context: .
dockerfile: ConsoleAppDocker/Dockerfile
container_name: "consoleappdocker"
command: ["/bin/bash", "-c", "echo test"]
that still fails with tail: invalid number 'echo test' error, however I just noticed this output:
docker ps -a --no-trunc
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
%id% consoleappdocker:dev "tail -f /dev/null /bin/bash -c 'echo test'" 7 minutes ago Exited (1) 7 minutes ago consoleappdocker
so it looks like @VonC is right, however I have no ideas where this tail part has been initially added
UPDATE6 :
Apparently the tail part is added by visual studio that I used to build and run my application, I found it in the logs:
docker-compose -f "%PATH%\docker-compose.yml" -f "%PATH%\docker-compose.override.yml" -f "%PATH%\obj\Docker\docker-compose.vs.debug.g.yml" -p dockercompose14997374556887134345 --ansi never --profile "*" config
name: dockercompose14997374556887134345
services:
consoleappdocker:
build:
context: %PATH%
dockerfile: ConsoleAppDocker/Dockerfile
labels:
com.microsoft.created-by: visual-studio
com.microsoft.visual-studio.project-name: ConsoleAppDocker
command:
- /bin/bash
- -c
- echo test
container_name: consoletest
entrypoint:
- tail
- -f
- /dev/null
environment:
..
image: consoleappdocker:dev
labels:
..
networks:
default: null
tty: true
volumes:
..
networks:
default:
name: dockercompose14997374556887134345_default
docker-compose -f "%PATH%\docker-compose.yml" -f "%PATH%\docker-compose.override.yml" -f "%PATH%\obj\Docker\docker-compose.vs.debug.g.yml" -p dockercompose14997374556887134345 --ansi never build
quite unexpected case, but I think it's more or less clear what to do next
The
commanddirective in thedocker-compose.ymlfile is used to override the defaultCMDspecified in theDockerfile.The
commanddirective is equivalent to the command you would pass afterdocker run <image> <command>.You are seeing an error about
tailbecause your Dockerfile is likely configured to run a command that involvestailat the end of its execution, and when you override the command in thedocker-compose.ymlfile, thetailcommand is trying to read a file namedecho "test", which does not exist.In your case, you want to run a command inside the container. The
docker-compose.ymlshould look like this:This will execute the command
echo testinside the container.For running complex commands or scripts, you can:
Add the scripts to the Docker image during the build, and then call the script from the
commanddirective.Add the script to the Docker image during the build, and call the script from the
CMDorENTRYPOINTin theDockerfile.Mount a volume with the script to the container, and call the script from the
commanddirective in thedocker-compose.yml.For your final note about running integration tests, you could add a script that runs your tests to the Docker image and then call that script in the
commanddirective. The script could look something like this:Then in your
docker-compose.yml:Do replace "
/path/to/your/script.sh" with the actual path to your script in the Docker container.And make sure your script have execution permissions. You can set these during the Docker build with the
RUNdirective:Do replace "
./host/path/to/your/script.sh" with the path to your script on the host.The Dockerfile you have provided does not show a
CMDorENTRYPOINTinstruction that involves thetailcommand. However, the error message you are seeing indicates that thetailcommand is being run and is attempting to open 'echo "test"' as a file, which suggests thattailis being invoked somewhere.It is also possible that
tailis being run as part of the base image or a parent image, or by some process within the container. If the base image or parent image has aCMDorENTRYPOINTthat includestail, and you are not overwriting it in your Dockerfile, that could explain why you are seeing thetailcommand in your error message.One common use of
tail -f /dev/nullin a Dockerfile is to keep a container running indefinitely, even if its main process has terminated (as I did here). This is sometimes used in development environments or for services that need to stay up but might not always have a process to run.If
tailis being invoked in this way, trying to replace thetail -f /dev/nullcommand with something else (likeecho "test") could lead to the error message you are seeing.To confirm this, you could examine the base or parent images, or any scripts or commands being run in the Dockerfile or the
docker-compose.ymlfile.If the
ENTRYPOINTin your Dockerfile or in a base image is set to atailcommand, and you are using thecommanddirective in your docker-compose file to runbash -c "echo test", Docker will try to append thecommandto theENTRYPOINTcommand.In this case, it would try to execute something like
tail bash -c "echo test", which is not a valid command and would cause the error you are seeing.You find a similar "invalid number" error here, where the base image alpine does not have a bash, and where built-in commands don't have all the more common options.
Same idea in "BUSYBOX script is wrong"
You can see that practice mentioned before (VS 2019) and here.
As mentioned in "Azure Function in Docker Container runs in Visual Studio, but does nothing from command line":
Official documentation:
So check your project properties file for a section like: