I'm trying to copy a bash file called setup_envs.sh which is in the same directory of my Dockerfile.
How can I run this bash file only once after Dockerfile is created?
My code is (in the end of the Dockerfile):
RUN mkdir -p /scripts
COPY setup_env.sh /scripts
WORKDIR /scripts
RUN chmod +x /scripts/setup_env.sh
CMD [./scripts/setup_env.sh]
Current error:
/bin/bash: [./scripts/setup_env.sh]: No such file or directory
I don't have a type in the file btw, I checked this.
Moreover, after I solve this and run the image to create a container - how can I make sure this bash script is only called once? Should I just write a command in the bash script that checks if some folder exists - and if it does - don't install it?
Based on the different comments including mine, this is what your Dockerfile extract should be replaced with:
COPY --chmod 755 setup_env.sh /scripts/
WORKDIR /scripts
CMD /scripts/setup_env.sh
Alternatively you can use the exec form for CMD but there is not much added value here since you're not passing any command line parameters.
CMD ["/scripts/setup_env.sh"]
At this point, I'm not really sure the WORKDIR instruction is useful (it depends on the rest of your Dockerfile and the content of your script).
Regarding your single bash script execution, I think you need to give a bit more background on the exact goal you are targeting. I have the feeling you could be in an X/Y Problem. And since this is a totally different issue, it should go inside a new question anyway with all required details.
Related
I am trying, as part of an exercise, to create an image and run a simple bash script. This is my Dockerfile:
FROM ubuntu
RUN chmod 700 .
#Create container to store file in
RUN mkdir doc-conatiner
# source then the destination of container in docker if I have one
COPY . /functionfibonnaci/doc-conatiner
#when conatiner starts what is the executable
CMD ["bash", "functionfibonnaci.sh"]
when I run docker run:
bash: functionfibonnaci.sh: No such file or directory```
No such file or direcotry
I have been at this for two days and just cant get this to work- so answers will be appreiacted.
As #KapilKhandelwal indicates in their answer, you're having trouble because the bash functionfibonnaci.sh command is looking for the script in the current directory, but you've never changed directories, so you're in the container filesystem's root directory.
I'd suggest updating this in a couple of ways:
On your host system, outside of Docker, make sure that the script starts with a "shebang" line; the very first line, starting at the very first character, should be #!/bin/sh (or if you have bash-specific extensions and can't remove them, #!/bin/bash, but try to stick to POSIX shell syntax if you can).
On your host system, outside of Docker, make sure the script is executable; chmod +x functionfibonnaci.sh. With this and the previous step, you'll be able to just run ./functionfibonnaci.sh without explicitly mentioning the shell.
In the Dockerfile, change WORKDIR to some directory early. Often a short directory name like /app works well.
You don't need to RUN mkdir the WORKDIR directory or directories you COPY into; Docker creates them for you.
When you COPY content into the Dockerfile, the right-hand side can be a relative path like ., relative to the current WORKDIR, so you don't need to repeat the directory name.
In your CMD you can also specify the script location relative to the current directory.
These updates will get you:
FROM ubuntu
# do not need to mkdir this directory first
WORKDIR /app # or /functionfibonnaci/doc-conatiner if you prefer
# copy the entire build-context directory into the current workdir
COPY . .
# the command does not need to explicitly name the interpreter
# (assuming the script has a "shebang" line and is executable)
CMD ["./functionfibonnaci.sh"]
From the error message, it is clear that functionfibonnaci.sh is not found.
Update the CMD command in the Dockerfile to this:
CMD ["bash", "/functionfibonnaci/doc-conatiner/functionfibonnaci.sh"]
Note: This will work if the functionfibonnaci.sh file is in the same directory where the Dockerfile is present on the host machine. If it is present in a different directory, feel free to update the path of the file in the CMD accordingly.
TL;DR
Let's look closely what you are trying to do. The first two lines of the Dockerfile are self-explainatory.
In the third command, you are creating a directory with the intention to copy your script files. Sounds good so far!!!
The fourth line of the Dockerfile is what created a mess IMO. You are actually copying all the files from host to the directory /functionfibonnaci/doc-conatiner. But wait, you were supposed to copy those file inside the doc-conatiner directory that you created earlier.. right?
Now in the last line of the Dockerfile, you are trying to run the bash script functionfibonnaci.sh. But now, since the default WORKDIR is / by default, it will search for the functionfibonnaci.sh file inside the / directory. This file is actually present inside the /functionfibonnaci/doc-conatiner directory.
Hence, you are facing this issue.
inside my makefile I have the following...
install:
$(INSTALL) $(PWD)/run.sh $(bindir)/run
so when the user clones my repo and CDs into it, I want them to type make install
my hope is that they will then be able to call the run.sh script as run
does anyone have any idea how this could be achieved?
If you want to install it globally then what you need is to copy it to a system-wide binary directory (like /usr/local/bin f.e.), and if you don't want them to need to use the .sh then you need to rename it to just run during the copy and add a shebang to the file (#!/bin/sh at the top).
One thing to keep in mind is that you might need to chmod +x $(bindir)/run if the file hasn't been marked as executable before.
I am trying to build me a Dockerfile for my ROS project.
In ROS it is required that you source a setup bash in every terminal before starting to work.
(You can replace this by putting the source command in your bashrc file)
So, what I do is to source the file in the Dockerfle so that it gets run when the container is built. It works fine on that terminal
However when I open another terminal , predictably it seems that that file is not sourced and I have to do it manually.
Is there any way I can avoid this?
As I said in a non docker way, you put this into a file that gets called everytime a terminal is open but how do you do this with docker?
(in other words, how do you make sure a sh file is executed everytime I execute (or attach to) a docker container)
In your Dockerfile, copy your script to Docker WORKDIR:
COPY ./setup.bash .
Then set the entry point to run that script at container launch:
ENTRYPOINT ["/bin/bash", "-c", "./setup.bash"]
Note that with this approach, you won't be able to start your container in an interactive terminal with docker run -it. You'll need to do a few more things if that's what you want. Also, this will overwrite your original image's ENTRYPOINT (which you can find by docker image history), so make sure that is not essential. Otherwise, sourcing the script may be the better option for both cases:
RUN source ./setup.bash
Just add the script to startup configuration files in bash...
COPY ./setup.bash /etc/
RUN echo "source /etc/setup.bash" >> /etc/bash.bashrc
ENTRYPOINT /bin/bash
The file /etc/bash.bashrc might be named /etc/bashrc, or you might want to use /etc/profile.d directory, depending if you want the file to be sourced in interactive shells or not. Read the relevant documentation about startup files in bash.
I have project structure like this
project
|app
|script
inside script folder, there are files such as 'run'
run file content:
#!/bin/bash
npm start
I want to run the file 'run' while I'm at the root of my project by typing only command 'run'. How would you do this?
This is sh file. In order to execute sh file on linux this file has to be executable.
Make sure this file has X permission.
If there is no x permission on file simply execute the command
chmod +x run.sh
Then execute the file by typing
./run.sh
For windows you need to create .bat file.
I'm not quite sure what you want but assuming you need a way to execute a file from node.js, you can use child_process module and child_process.exec method to start any executable.
Assuming the run file in the script directory is executable (if not, run chmod +x script/run), it can be executed by running ./script/run.
If you want to avoid having to type the name of the directory (script), you could append the script directory to your PATH environment variable. If you’re running a POSIX compatible shell (not csh or tcsh), this can be done using:
export PATH="$PATH:/path/to/project/script"
This will allow you to run any executable command in the script directory without having to specify the name of the directory, e.g., run.
NB: be sure that there aren’t common command names in the script directory as these commands can be run from any directory (including outside the project directory) after it has been added to the PATH. That’s also why I suggest adding it to the end of the PATH (so it’s the last directory that’s searched for executable commands).
This question already has answers here:
Why do you need ./ (dot-slash) before executable or script name to run it in bash?
(9 answers)
Closed 2 years ago.
In ubuntu scripts can be executed with following commands:
$ chmod +x manage.py
$ manage.py
However in mac you need to use ./ in order to actually run the script, as follow:
$ chmod +x manage.py
$ ./manage.py
I would like to know what is exactly ./ (especially that both system use bash by default) and if there is a way to run scripts directly in mac?
It's because you (very sensibly) don't have . in your PATH environment variable. If you do, it becomes an attack vector for people to get you to execute their own code instead of real stuff.
For example, let's say your path is:
.:/usr/bin
so that commands will first be searched for in your current directory, then in /usr/bin.
Then another user creates an executable script file ls in their home directory which changes to your home directory and deletes all your files. Then they tell you they've got something interesting in their home directory. You run ls to see what they have, and your files are deleted. All because it ran ls from your current directory first.
This is a particular favorite attack vector against naive system admins.
To be honest, on my home machines, I don't worry too much, since I'm the only user and I'm not prone to downloading stuff I don't trust. So I usually add . to my path for convenience, but usually at the end so it doesn't get in the way of my more regular commands.
When you are executing a command that file (script/binary) needs to be found by the system. That is done by putting directories where to look for scripts into the PATH environment variable. So if it works in ubuntu it means PATH includes '.' (the current directory). If you want the same behavior on mac then put something like export PATH="$PATH:." in your .bashrc (asuming you are using bash..)