how do you manage secret values with docker-compose v3.1?
You can read the corresponding section from the official documentation.
To use secrets you need to add two things into your docker-compose.yml
file. First, a top-level secrets:
block that defines all of the secrets. Then, another secrets:
block under each service that specifies which secrets the service should receive.
As an example, create the two types of secrets that Docker will understand: external secrets and file secrets.
1. Create an 'external' secret using docker secret create
First thing: to use secrets with Docker, the node you are on must be part of a swarm.
$ docker swarm init
Next, create an 'external' secret:
$ echo "This is an external secret" | docker secret create my_external_secret -
(Make sure to include the final dash, -
. It's easy to miss.)
2. Write another secret into a file
$ echo "This is a file secret." > my_file_secret.txt
3. Create a docker-compose.yml
file that uses both secrets
Now that both types of secrets are created, here is the docker-compose.yml
file that will read both of those and write them to the web
service:
version: '3.1'
services:
web:
image: nginxdemos/hello
secrets: # secrets block only for 'web' service
- my_external_secret
- my_file_secret
secrets: # top level secrets block
my_external_secret:
external: true
my_file_secret:
file: my_file_secret.txt
Docker can read secrets either from its own database (e.g. secrets made with docker secret create
) or from a file. The above shows both examples.
4. Deploy your test stack
Deploy the stack using:
$ docker stack deploy --compose-file=docker-compose.yml secret_test
This will create one instance of the web
service, named secret_test_web
.
5. Verify that the container created by the service has both secrets
Use docker exec -ti [container] /bin/sh
to verify that the secrets exist.
(Note: in the below docker exec
command, the m2jgac...
portion will be different on your machine. Run docker ps
to find your container name.)
$ docker exec -ti secret_test_web.1.m2jgacogzsiaqhgq1z0yrwekd /bin/sh
# Now inside secret_test_web; secrets are contained in /run/secrets/
root@secret_test_web:~$ cd /run/secrets/
root@secret_test_web:/run/secrets$ ls
my_external_secret my_file_secret
root@secret_test_web:/run/secrets$ cat my_external_secret
This is an external secret
root@secret_test_web:/run/secrets$ cat my_file_secret
This is a file secret.
If all is well, the two secrets we created in steps 1 and 2 should be inside the web
container that was created when we deployed our stack.
How to use secrets when building docker compose locally
Support for this was recently implemented in v2. See the below pull requests.
- https://github.com/docker/compose/pull/9386
- https://github.com/compose-spec/compose-spec/pull/238
The provided example looks like this:
services:
frontend:
build:
context: .
secrets:
- server-certificate
secrets:
server-certificate:
file: ./server.cert
So you are close, but you have to add the secret key under the build key.
Also keep in mind that you have to use docker compose
instead of docker-compose
, in order to use v2 which is built into the docker client.
Pass docker-compose secret to Dockerfile
I've gotten this working with slight changes to your docker compose:
version: '3.8'
services:
worksnow:
build:
context: .
secrets:
- mysecret
entrypoint: cat /run/secrets/mysecret
secrets:
- mysecret
secrets:
mysecret:
file: ./secret
$ docker compose up
[+] Running 1/1
⠿ Container docker-compose-secrets-worksnow-1 Recreated 0.1s
Attaching to docker-compose-secrets-worksnow-1
docker-compose-secrets-worksnow-1 | cool
docker-compose-secrets-worksnow-1 exited with code 0
It seems like the trouble is that the secret is needed during the build in order for Docker to successfully interpret the RUN
statement. Once you actually run the container, of course, it also needs the secret to be available then in order to access it.
RUN
is a container build step, so (confusingly) it's not going to be executed when the container is actually run. That's why I needed to add an entrypoint
to get the output to show up.
In case you're wondering if including the secrets in the build step is somehow storing the secret in the image, it's not. We can test this using Google's container-diff.
$ container-diff diff --type=file daemon://busybox daemon://docker-compose-worksnow
-----File-----
These entries have been added to busybox:
FILE SIZE
/proc 0
/run 0
/run/secrets 0
/sys 0
These entries have been deleted from busybox: None
These entries have been changed between busybox and docker-compose-notworking: None
How do I configure a secret in docker compose?
Setting a secret only exposes that value at a filesystem location under /run/secrets
. If you want to get that value into a variable, you would need to do that yourself as part of your container startup.
For example, an ENTRYPOINT
script like that this would make /run/secrets/username
available as DB_USERNAME
:
#!/bin/sh
if [ -f /run/secrets/username ]; then
export DB_USERNAME=$(cat /run/secrets/username)
fi
exec "$@"
Secrets in docker compose
Apparently this is not supported for "docker compose", only for "docker swarm". The docs are misleading.
Docker Compose doesn't support real (swarmkit) secrets, and imitates them by bind-mounting the file directly into the container (which means that permissions on the host are the same as in the container).
You can change the ownership of the file on the host to match the uid/gid of the user in the container, but otherwise I don't think there's much that can be done unfortunately
UPDATE 2022
If you want this functionality, please upvote this PR, and/or add some comments, so the developers know how badly we want this feature. That PR was supposed to add this feature, but was not completed.
How to use 'mode' with docker secrets mounted with files?
I believe this is just a limitation for how docker compose
implements the spec. The fields were originally added for Swarm Mode which loads the secret into the database, and pushes it to nodes in the swarm on a need to know basis. Those nodes load the file into a tmpfs file that gets mounted into the container, and in that tmpfs file, they are adjusting the permissions and ownership.
With compose, I expect that to be implemented with a bind mount since there's no swarm manager and database to store the secrets in. And with a bind mount, there's no option to change the permissions and ownership between the source and target of the bind, the Linux kernel will pass those directly through.
Related Topics
Laravel-Mix No Build Notification
How to Increase The Size of Ephemeral Storage in a Kubernetes Worker Node
How to Write Own Package for Recipe in Arago Project Build
Split and Rename The Splitted Files in Shell Script
Iptables Remove Specific Rules by Comment
Bash Script to Compile and Run C++ Program
End Perl Script Without Waiting for System Call to Return
In Gitlab Ci The Gitlab Runner Choose Wrong Executor
Page Fault in Interrupt Context
How to Avoid High CPU Usage While Reading/Writing Character Device
Overview/Reference Manual for Open Firmware Device Trees
How to Determine a Tar Archive's Format
Pipe Tar Extract into Tar Create
Changing Matlab's Startup Folder in Linux
Register Hotkey with Only Modifiers in Linux
Removing Parts of a String That Contain Digit with Sed/Perl