sourcing a setup.bash in a Dockerfile - bash

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.

Related

I have tried and really need some help in understanding why docker file wont run this script

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.

Dockerfile - copying a bash file from host to Dockerfile

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.

Git Bash file which runs command in current directory, then opens chrome

Per the title, I'd like to have a .sh file which I can drop into a directory and then:
Run http-server (the simple node server) in the current directory
Open Chrome and point it to that server
The idea is that when I'm developing I can quickly run this bash file and see the current version of whatever html/css/javascript website I am working on. My issue is that if you run a command in a bash file, it isn't run in the current working directory, but rather in the root directory (as far as I can tell). So if I just write http-server in my file, it will run a server not in the current directory, but in ./.
To fix this, I want to cd to the directory first, and then run the script. current_dir=$(pwd) will give me something close to the current directory, but I can't put that directly into a cd command because it (1) doesn't have quotes around it, so spaces in directory names will make it not work, and (2) it starts with /C/ instead of /C:/. Can anyone advise me on how to fix this?
My current code looks as follows.
curr_dir=$(pwd)
cd $curr_dir
http-server
start chrome localhost/XXX
And, as mentioned, results in the http-server command being run in the wrong place:
Starting up http-server, serving ./
Available on:
http://192.168.56.1:8081
http://192.168.1.21:8081
http://127.0.0.1:8081
Hit CTRL-C to stop the server
e: For anyone who happens on this later, this isn't actually a problem -- see the accepted answer. I had another typo.
No; the commands you run always run in the current directory. Otherwise, if your hypothesis were correct, e.g. ls would always show the files in the root directory.
If you want to run a command which is in a different directory, you want
../relative/path/to/command
or
/absolute/path/to/command
Neither of these change the current directory of the shell. The current working directory of the process you create will remain the directory you were in when you run this command. (Even if you run it in the background and subsequently change to a different directory in your interactive shell, for example.)
If you want the command to run in the directory where the script lives on the disk, something like this can occasionally be useful.
cd "$(dirname "$0")"
but again, most of the time, you want and need your commands to run in the current directory.
(There are situations where you want a script to process data files in a fixed location, but these are rare exceptions. Until you have such a situation, consider it a bug to use cd in a shell script.)
If you have a command http-server somewhere on your PATH, just http-server will run that. You should normally not have the current directory on the PATH, but to run the binary in the current directory instead of from anywhere on the PATH, you say so:
./http-server

how to run script with simple command

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).

How to source a file via shell script

I wrote a shell script where I copy my .bashrc file as well as custom dotfiles to a backup folder and then replace them in my home folder with another .bashrc file which will then source my custom dotfiles.
However, after the script does its job, if I try to execute the aliases I included in the new files I get the error No command found. Only after I source the .bashrc file manually in the terminal I have access to them.
From what I understand, the script I'm running is executing in a sub-shell (?) which will terminate on execution.
How can I run the script and have new commands/aliases/functions available without having to source the .bashrc file myself or restarting the terminal?
Well, it appears that instead of running my script via sh script.sh, I can source it like source script.sh, which will behave exactly as I wanted.
Solution

Resources