I have this script with some commands like:
sudo docker exec $container psql -U postgres -c "CREATE DATABASE $gisdb ;"
The $container parameter is no problem, but I cannot get the right value read with $gisdb parameter in the CREATE DATABASE command. Is it possible any other way or do I need to redesign this command or use hardcoded values?
DB name
According to PostgreSQL Documentation, creating database requires name of the database
CREATE DATABASE _name_
So, $gisdb in your code - is the name of the created database.
You might hardcode this name, but you should exactly know - which name you' hardcode.
Because, generally, other services depends on DB name.
So, check the manual of your code.
get rid of sudo
You can omit sudo before docker command.
Just add current user to the docker group:
usermod -aG docker $USER
And then, after login, you'll be able to run docker without sudo
Related
My goal is to understand:
How Docker can do $ su to nonexistent user? e.g $ docker run -it --rm -u 10001:10001 alpine:3.16
Is it safe to use $ docker run -u or USER variable in Dockerfile with a nonexistent user? I mean, is it possible if the container is compromised, they can do something nasty because the user technically does not exist?
The problem is, I can't achieve it even with root. What I've tried:
$ su nobody <- the shell is /sbin/nologin. So, it throws This account is not available.
$ docker run -it --rm -u nobody:nobody alpine:3.16, it works.
$ su nonexistent <- no record in /etc/passwd. So, it throws su: unknown user nonexistent.
$ docker run -it --rm -u 10001:10001 alpine:316, it works.
$ docker run -it --rm -u nonexistent:nonexistent alpine:3.16, the docker daemon will throw docker: Error response from daemon: unable to find user nonexistent: no matching entries in passwd file., it is expected.
Dockerfile
FROM alpine:3.16
USER 10001:10001
How Docker can do $ su...
Usually it can't. A typical Docker container won't have a root password or any other password set, and it may not even have the su binary.
This isn't typically a problem since a Docker container only runs a single process, and you can explicitly set the user ID when you start the container with...
docker run -it --rm -u 10001:10001 alpine:3.16
The important thing about Unix user and group IDs is their numeric value. For example, there's nothing special about the user name root, but if the current user has the numeric user ID 0 then it has special privileges. Similarly, this command sets both the user and group IDs to 10001; it can write files if they have user- or group-write permission and are owned by exactly that numeric user or group ID. There's no requirement that a user or group "exist" per se.
Particularly in a Docker context, this can come up routinely with bind-mounted host directories. The container's numeric user ID needs to match the numeric user ID that owns the files on the host, but there's no requirement to "create the user".
Is it safe to use $ docker run -u or USER variable in Dockerfile with a nonexistent user?
Yes. The two things that are important are (a) whether or not the numeric user ID is 0 and (b) whether the numeric user ID matches the ownership of files in the container or mounted volumes. If the numeric user ID doesn't match then the user won't be able to overwrite files.
It's possible some application code might try to find out the current user name and get confused when it doesn't exist. If you're using bash as a debugging shell it might print a "no such user" complaint as part of the prompt, but this is totally cosmetic.
A more specific statement: it's safe to do something like
docker run -u $(id -u):$(id -g) -v "$PWD:/data" ...
to both set the numeric user and group ID of the container to match the host, and to mount the current directory into the container somewhere. There's no requirement to "create the user" before you do, and it's not an especially good practice to build an image that has a specific host user ID built in.
Docker, docker-compose have been installed according to docker docs for fresh install of Ubuntu 20.04.
When I try to run the compose command I get the following error:
***DOCKER_WWWROOT is not set or not an existing directory.
I have previously run export ***DOCKER_WWWROOT=/path/to/myproject and have conifrmed the path is correct by running export.
The declare -x ***DOCKER_WWWROOT value shows my correct path. The directory does exist.
Any help is appreciated. The ***'s are just placeholders for the template brand name.
My install process was missing a step. Needed to add user group to run docker as a non-root user https://docs.docker.com/engine/install/linux-postinstall/
From the docker docs:
Create docker group sudo groupadd docker
Add user to group sudo usermod -aG docker $USER Activate group changes newgrp dockerVerify docker can be run without sudo commandsdocker run hello-world`
When i run this command by ssh into aws instance
docker run hello-world
aws ecr get-login --no-include-email --region ap-south-1 > ./login
source ./login
it output
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
WARNING! Your password will be stored unencrypted in /home/ubuntu/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
Which is success.
But when enter same command in jenkins like
output is
I added user by
sudo usermod -a -G docker jenkins
sudo usermod -a -G docker user
What is going wrong ?
source isn't a standard shell command; it's not one of the "special built-in utilities" in the POSIX.1 spec. Some shells happen to have a command named source but it's not required to be present.
There is a similar standard command . that executes a file in the context of the current shell. If you're using the bash-specific source, you can usually just change that to the standard . without making any further changes
. ./login
Note that . searches $PATH for the file to run; it will not search the current directory unless specifically told to. Also note that you typically only use . for scripts that have side effects like setting environment variables, and in a context like what you show where each command is running in a separate shell, this won't have longer-lasting effects.
Since the output of the aws ecr get-login command is a single docker login command that doesn't directly change the shell context, you can also just run it as a shell script
sh ./login
I want to sync the host machine's user/group with the docker machine to enable (developers) to edit the files inside or outside the container. There are some ideas like this: Handling Permissions with Docker Volumes which creates a new user.
I would like to try a similar approach, but instead of creating a new user, I would like to modify the existing user using usermod:
usermod -d /${tmp} docker # avoid `usermod` from modifying permissions automatically.
usermod -u "${HOST_USER_ID}" docker
groupmod -g "${HOST_GROUP_ID}" docker
usermod -d ${HOME} docker
This idea seems to work, but when the container is run as docker user (which is what I want), usermod complains that "this user has a process running and so it can't change the user id".
If add sudo, it will change the user id, but it will break on the next sudo will the following exception: sudo: unknown uid 1000: who are you? as a consequence of side-stepping the above problem.
sudo usermod -d /${tmp} docker
sudo usermod -u "${HOST_USER_ID}" docker
sudo groupmod -g "${HOST_GROUP_ID}" docker # `sudo: unknown uid 1000: who are you?`
sudo usermod -d ${HOME} docker # `sudo: unknown uid 1000: who are you?`
Is it possible to run something as a root when the container is started, along with a bootstrap script as a normal user? It seems like the Dockerfile's CMD doesn't executes two commands; nor can I club multiple commands into one script sine I need to run as two users - or can I? I know I can create a different image, but wondering if there are cleaner alternatives.
You can start your container as root, allow the ENTRYPOINT script to perform any changes you want, and then switch to an unprivileged user when you execute the container CMD. E.g., use an ENTRYPOINT script something like this:
#!/bin/sh
usermod -d /${tmp} docker
usermod -u "${HOST_USER_ID}" docker
groupmod -g "${HOST_GROUP_ID}" docker
exec runuser -u docker -- "$#"
If you don't have the runuser command, you can get similar behavior using su.
I have a docker container with a -v /home/dan:/home/dan:rw. When the container writes files to /home/dan, the files are owned by root in the host filesystem. Is there a way to make it so that files written from the container to the mounted volume are owned by some arbitrary user on the host filesystem?
As François Zaninotto has pointed out, the user id can be used.
This can be done by using the -u switch for the docker run command.
For example:
docker run -v /home/dan:/home/dan -u `id -u $USER` IMAGE
EDIT: this has changed since my original answer which said it couldn't be done. As per answer of Mandark:
This can be done by using the -u switch for the docker run command.
For example:
docker run -v /home/dan:/home/dan -u `id -u $USER` IMAGE
A follow up to mandark answer - I would say it's also good to include the user group otherwise you will end up with stuff belonging to user: USER and group: root. To achive user:user just pass in group id as well, for example:
docker run -v /home/dan:/home/dan -u `id -u $USER`:`id -g $USER` IMAGE
# if it's for the current user, then you can omit the $USER env var
docker run -v /home/dan:/home/dan -u `id -u`:`id -g` IMAGE
It's possible. It's hard to automate, but it's possible. Here is the process:
in the host, determine the current user id and group id
in the docker container, run a shell script to:
add a new group with the group id from the host
add a new user with the same user id from the host (and belonging to the group just created)
sudo as this new user
Now, each file generated inside the container will be using the right user id and group id, and the host will attach them to your user.
I've written a tool to automate that using make, it's called make-docker-command. Hope this helps.