Home > Software engineering >  docker copy and chown in bash script
docker copy and chown in bash script

Time:04-22

I'm building a network with docker compose and some bash scripts and i'm having problems during the process. Basically i have a some containers and volumes. In one of the container i have to rename a file and copy it in a volume to make it accesible to other containers. The problem is that this file is regenerated with a different name every time i start the network (this because it's a key) so i don't know its name. If i try with this command in the container:

docker exec -it containerName cp /path_in_container/* /volume/key.pem

docker give me an error related to the path. The same thing happen if i use

docker exec -it containerName cp /path_in_container/. /volume/key.pem

If i insert the real name this way:

docker exec -it containerName cp /path_in_container/2164921649_sk /volume/key.pem

i have no problem but, how i already explained, i can't know its name.

I tried to solve the problem copying the file from the linked volume folder directly in my system but, since the folder is protected, i need to use:

sudo chown -R user:user /tmp/path/*

In this case, the problem is that if I enter the chown command in a bash script, I then have to enter the password and it doesn't always work.

So I would like to try to copy the file directly from the container by making a copy of all the files in the folder or make the bash script run with the chown command inside, before the various copy operations, without entering the password. Can someone help me? Thanks

EDIT: This is a part of the code useful to understand the problem

#Copy TLS-CA certificate
docker exec -it tls-ca cp /tmp/hyperledger/fabric-ca/admin/msp/cacerts/tls-ca-7051.pem /certificates/tls-ca-7051.pem

echo "Start operation for ORG0"
#ENROLL ORDERER

# for identity
docker exec -it rca-org0 fabric-ca-client enroll -d -u https://orderer1-org0:ordererpw@rca-org0:7052 --tls.certfiles /tmp/hyperledger/fabric-ca/admin/msp/cacerts/rca-org0-7052.pem --home /tmp/hyperledger/fabric-ca-enrollment/orderer --mspdir msp
sleep 5
# for TLS
docker exec -it rca-org0 fabric-ca-client enroll -d -u https://orderer1-org0:ordererPW@tls-ca:7051 --enrollment.profile tls --csr.hosts orderer1-org0 --tls.certfiles /certificates/tls-ca-7051.pem --home /tmp/hyperledger/fabric-ca-enrollment/orderer --mspdir tls-msp
sleep5
#ENROLL ADMIN USER
docker exec -it rca-org0 fabric-ca-client enroll -d -u https://admin-org0:org0adminpw@rca-org0:7052 --tls.certfiles /tmp/hyperledger/fabric-ca/admin/msp/cacerts/rca-org0-7052.pem --home /tmp/hyperledger/fabric-ca-enrollment/admin/ --mspdir msp
sleep 5
#CREATE NECESSARY FOLDERS

docker exec rca-org0 cp /tmp/hyperledger/fabric-ca-enrollment/orderer/tls-mps/keystore/*
chown -R fabrizio:fabrizio /tmp/hyperledger/*

mv /tmp/hyperledger/org0/orderer/tls-msp/keystore/* /tmp/hyperledger/org0/orderer/tls-msp/keystore/key.pem
mkdir -p /tmp/hyperledger/org0/orderer/msp/admincerts
cp /tmp/hyperledger/org0/admin/msp/signcerts/cert.pem /tmp/hyperledger/org0/orderer/msp/admincerts/orderer-admin-cert.pem

mkdir /tmp/hyperledger/org0/msp
mkdir /tmp/hyperledger/org0/msp/{admincerts,cacerts,tlscacerts,users}
cp /tmp/hyperledger/org0/ca/admin/msp/cacerts/rca-org0-7052.pem /tmp/hyperledger/org0/msp/cacerts/org0-ca-cert.pem
cp /tmp/hyperledger/certificates/tls-ca-7051.pem /tmp/hyperledger/org0/msp/tlscacerts/tls-ca-cert.pem
cp /tmp/hyperledger/org0/admin/msp/signcerts/cert.pem /tmp/hyperledger/org0/msp/admincerts/admin-org0-cert.pem
cp ./org0-config.yaml /tmp/hyperledger/org0/msp/config.yaml

CodePudding user response:

In the script you show, you run a series of one-off commands in an existing container, and then need to manage the container filesystem. It might be more straightforward to script a series of docker run commands, that can use docker run -v bind mounts to inject input files into the container and get the output files back out.

docker run --rm \
  -v "$PWD/cacerts:/cacerts" \
  -v "$PWD/certs:/certs" \
  image-for-fabric-ca-client \
  fabric-ca-client enroll \
    -d \
    -u https://orderer1-org0:ordererpw@rca-org0:7052 \
    --tls.certfiles /cacerts/rca-org0-7052.pem \
    --home /certs \
    --mspdir msp

If this invocation has the TLS CA certificates used as input in ./cacerts, and the resulting TLS server certificates as output in ./certs, then you've "escaped" Docker space; you can use ordinary shell commands here.

mv ./certs/*_sk ./certs/key.pem

Depending on what the fabric-ca-client enroll command actually does, it might be possible to run it as the same user ID as on the host

docker run \
  -u $(id -u) \
  -v "$PWD/certs:/certs" \
  ...

So long as the host ./cacerts directory is world-readable and the ./certs directory is writable by the current user, the main container process will run as the same (numeric) user ID as on the host, and the files will be readable without chown.

In general I'd recommend avoiding docker exec and docker cp in scripts, in much the same way you don't use a debugger like gdb for routine tasks like generating CA certificates.

Also consider the possibility that you may need to run this script as root anyways. TLS private keys typically aren't readable by other than their owner (mode 0600 or 0400) and you might need to chown the files to the eventual container users, which will require root access. Also note in the last docker run invocation that nothing stops you from specifying -u root or mounting a "system" host directory -v /host-etc:/etc, so it's very easy to use docker run to root the host; on many systems access to the Docker socket will be very reasonably restricted to require sudo access.

  • Related