Skip to content

Commit 83cafe2

Browse files
committed
Add support to pass env-from-file to docker compose run
Signed-off-by: Vedant Koditkar <[email protected]> Signed-off-by: Nicolas De Loof <[email protected]>
1 parent 55b5f23 commit 83cafe2

File tree

6 files changed

+51
-2
lines changed

6 files changed

+51
-2
lines changed

cmd/compose/run.go

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@ package compose
1919
import (
2020
"context"
2121
"fmt"
22+
"os"
2223
"strings"
2324

25+
"github.com/compose-spec/compose-go/v2/dotenv"
2426
"github.com/compose-spec/compose-go/v2/format"
2527
xprogress "github.com/moby/buildkit/util/progress/progressui"
2628
"github.com/sirupsen/logrus"
@@ -44,6 +46,7 @@ type runOptions struct {
4446
Service string
4547
Command []string
4648
environment []string
49+
envFiles []string
4750
Detach bool
4851
Remove bool
4952
noTty bool
@@ -116,6 +119,29 @@ func (options runOptions) apply(project *types.Project) (*types.Project, error)
116119
return project, nil
117120
}
118121

122+
func (options runOptions) getEnvironment() (types.Mapping, error) {
123+
environment := types.NewMappingWithEquals(options.environment).Resolve(os.LookupEnv).ToMapping()
124+
for _, file := range options.envFiles {
125+
f, err := os.Open(file)
126+
if err != nil {
127+
return nil, err
128+
}
129+
vars, err := dotenv.ParseWithLookup(f, func(k string) (string, bool) {
130+
value, ok := environment[k]
131+
return value, ok
132+
})
133+
if err != nil {
134+
return nil, nil
135+
}
136+
for k, v := range vars {
137+
if _, ok := environment[k]; !ok {
138+
environment[k] = v
139+
}
140+
}
141+
}
142+
return environment, nil
143+
}
144+
119145
func runCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service) *cobra.Command {
120146
options := runOptions{
121147
composeOptions: &composeOptions{
@@ -175,6 +201,7 @@ func runCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service) *
175201
flags := cmd.Flags()
176202
flags.BoolVarP(&options.Detach, "detach", "d", false, "Run container in background and print container ID")
177203
flags.StringArrayVarP(&options.environment, "env", "e", []string{}, "Set environment variables")
204+
flags.StringArrayVar(&options.envFiles, "env-from-file", []string{}, "Set environment variables from file")
178205
flags.StringArrayVarP(&options.labels, "label", "l", []string{}, "Add or override a label")
179206
flags.BoolVar(&options.Remove, "rm", false, "Automatically remove the container when it exits")
180207
flags.BoolVarP(&options.noTty, "no-TTY", "T", !dockerCli.Out().IsTerminal(), "Disable pseudo-TTY allocation (default: auto-detected)")
@@ -264,6 +291,11 @@ func runRun(ctx context.Context, backend api.Service, project *types.Project, op
264291
buildForRun = &bo
265292
}
266293

294+
environment, err := options.getEnvironment()
295+
if err != nil {
296+
return err
297+
}
298+
267299
// start container and attach to container streams
268300
runOpts := api.RunOptions{
269301
Build: buildForRun,
@@ -278,7 +310,7 @@ func runRun(ctx context.Context, backend api.Service, project *types.Project, op
278310
User: options.user,
279311
CapAdd: options.capAdd.GetAll(),
280312
CapDrop: options.capDrop.GetAll(),
281-
Environment: options.environment,
313+
Environment: environment.Values(),
282314
Entrypoint: options.entrypointCmd,
283315
Labels: labels,
284316
UseNetworkAliases: options.useAliases,

docs/reference/compose_run.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ specified in the service configuration.
6666
| `--dry-run` | `bool` | | Execute command in dry run mode |
6767
| `--entrypoint` | `string` | | Override the entrypoint of the image |
6868
| `-e`, `--env` | `stringArray` | | Set environment variables |
69+
| `--env-from-file` | `stringArray` | | Set environment variables from file |
6970
| `-i`, `--interactive` | `bool` | `true` | Keep STDIN open even if not attached |
7071
| `-l`, `--label` | `stringArray` | | Add or override a label |
7172
| `--name` | `string` | | Assign a name to the container |

docs/reference/docker_compose_run.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,16 @@ options:
117117
experimentalcli: false
118118
kubernetes: false
119119
swarm: false
120+
- option: env-from-file
121+
value_type: stringArray
122+
default_value: '[]'
123+
description: Set environment variables from file
124+
deprecated: false
125+
hidden: false
126+
experimental: false
127+
experimentalcli: false
128+
kubernetes: false
129+
swarm: false
120130
- option: interactive
121131
shorthand: i
122132
value_type: bool

pkg/e2e/compose_run_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,4 +178,10 @@ func TestLocalComposeRun(t *testing.T) {
178178
assert.Assert(t, strings.Contains(res.Combined(), "backend Pulling"), res.Combined())
179179
assert.Assert(t, strings.Contains(res.Combined(), "backend Pulled"), res.Combined())
180180
})
181+
182+
t.Run("compose run --env-from-file", func(t *testing.T) {
183+
res := c.RunDockerComposeCmd(t, "-f", "./fixtures/run-test/compose.yaml", "run", "--env-from-file", "./fixtures/run-test/run.env",
184+
"front", "env")
185+
res.Assert(t, icmd.Expected{Out: "FOO=BAR"})
186+
})
181187
}

pkg/e2e/fixtures/run-test/compose.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
version: '3.8'
21
services:
32
back:
43
image: alpine

pkg/e2e/fixtures/run-test/run.env

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
FOO=BAR

0 commit comments

Comments
 (0)