Skip to content
This repository was archived by the owner on Jul 18, 2025. It is now read-only.

Commit ae5fefe

Browse files
authored
Merge pull request #292 from shin-/app-fork
Implement `docker-app fork`
2 parents a5a9076 + e8d2bb8 commit ae5fefe

18 files changed

Lines changed: 596 additions & 27 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
_build/
77
bin/
88
!examples/simple/*.dockerapp
9+
!e2e/**/*.dockerapp
910
.gradle
1011
coverage.html
1112
cover.out

README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,22 @@ $ docker pull myHubUser/hello.dockerapp:latest
204204
$ docker-app inspect myHubUser/hello
205205
```
206206

207+
## Forking an existing image
208+
209+
Found an app on a remote registry you'd like to modify to better suit your needs? Use the `fork` subcommand:
210+
211+
```bash
212+
$ docker-app fork remote/hello.dockerapp:1.0.0 mine/hello2 -m "Bob Dylan:bob@aol.com"
213+
```
214+
215+
This command will create a local, editable copy of the app on your system. By default, the copy is created inside the current directory; you may use the `--path` flag to configure a different destination.
216+
217+
For example, the following will create the `/opt/myapps/hello2.dockerapp` folder containing the forked app's files:
218+
219+
```bash
220+
$ docker-app fork remote/hello.dockerapp:1.0.0 mine/hello2 --path /opt/myapps
221+
```
222+
207223
## Next steps
208224

209225
We have lots of ideas for making Compose-based applications easier to share and reuse, and making applications a first-class part of the Docker toolchain. Please let us know what you think about this initial release and about any of the ideas below:
@@ -227,6 +243,7 @@ Usage:
227243
Available Commands:
228244
completion Generates bash completion scripts
229245
deploy Deploy or update an application
246+
fork Create a fork of an existing application to be modified
230247
helm Generate a Helm chart
231248
init Start building a Docker application
232249
inspect Shows metadata and settings for a given application

cmd/docker-app/fork.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package main
2+
3+
import (
4+
"github.com/docker/app/internal/packager"
5+
"github.com/docker/cli/cli"
6+
"github.com/spf13/cobra"
7+
)
8+
9+
var (
10+
forkMaintainers []string
11+
outputDir string
12+
)
13+
14+
func forkCmd() *cobra.Command {
15+
cmd := &cobra.Command{
16+
Use: "fork <origin-name> [fork-name] [-p outputdir] [-m name:email ...]",
17+
Short: "Create a fork of an existing application to be modified",
18+
Args: cli.RequiresRangeArgs(1, 2),
19+
RunE: func(cmd *cobra.Command, args []string) error {
20+
forkName := ""
21+
if len(args) >= 2 {
22+
forkName = args[1]
23+
}
24+
return packager.Fork(args[0], forkName, outputDir, forkMaintainers)
25+
},
26+
}
27+
cmd.Flags().StringArrayVarP(&forkMaintainers, "maintainer", "m", []string{}, "Maintainer (name:email) (optional)")
28+
cmd.Flags().StringVarP(&outputDir, "path", "p", ".", "Directory where the application will be extracted")
29+
30+
return cmd
31+
}

cmd/docker-app/root.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ func newRootCmd(dockerCli *command.DockerCli) *cobra.Command {
4343
func addCommands(cmd *cobra.Command, dockerCli command.Cli) {
4444
cmd.AddCommand(
4545
deployCmd(dockerCli),
46+
forkCmd(),
4647
helmCmd(),
4748
initCmd(),
4849
inspectCmd(dockerCli),

e2e/commands_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,3 +312,28 @@ func TestImageBinary(t *testing.T) {
312312
assertCommand(t, dockerApp, "inspect", "alice/envvariables:0.1.0")
313313
assertCommand(t, dockerApp, "inspect", "alice/envvariables.dockerapp:0.1.0")
314314
}
315+
316+
func TestForkBinary(t *testing.T) {
317+
dockerApp, _ := getDockerAppBinary(t)
318+
r := startRegistry(t)
319+
defer r.stop(t)
320+
registry := r.getAddress(t)
321+
assertCommand(t, dockerApp, "save", "--namespace", registry+"/acmecorp", "fork/simple")
322+
assertCommand(t, dockerApp, "push", "--namespace", registry+"/acmecorp", "fork/simple")
323+
324+
tempDir, err := ioutil.TempDir("", "dockerapptest")
325+
assert.NilError(t, err)
326+
defer os.RemoveAll(tempDir)
327+
328+
assertCommand(t, dockerApp, "fork", registry+"/acmecorp/simple.dockerapp:1.1.0-beta1", "acmecorp/scarlet.devil", "-p", tempDir, "-m", "Remilia Scarlet:remilia@acmecorp.cool")
329+
metadata, err := ioutil.ReadFile(filepath.Join(tempDir, "scarlet.devil.dockerapp", "metadata.yml"))
330+
assert.NilError(t, err)
331+
332+
golden.Assert(t, string(metadata), "expected-fork-metadata.golden")
333+
334+
assertCommand(t, dockerApp, "fork", registry+"/acmecorp/simple.dockerapp:1.1.0-beta1", "-p", tempDir, "-m", "Remilia Scarlet:remilia@acmecorp.cool")
335+
metadata2, err := ioutil.ReadFile(filepath.Join(tempDir, "simple.dockerapp", "metadata.yml"))
336+
assert.NilError(t, err)
337+
338+
golden.Assert(t, string(metadata2), "expected-fork-metadata-no-rename.golden")
339+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
version: "3.6"
2+
services:
3+
api:
4+
image: python:${versions.python}
5+
networks:
6+
back:
7+
front:
8+
aliases:
9+
- corp.app.api.com
10+
- ${api_host}
11+
web:
12+
image: nginx:${versions.nginx}
13+
networks:
14+
- front
15+
volumes:
16+
- static:/opt/${static_subdir}
17+
ports:
18+
- ${web_port}:80
19+
db:
20+
image: postgres:${versions.postgres}
21+
networks:
22+
- back
23+
networks:
24+
front:
25+
back:
26+
volumes:
27+
static:
28+
external: true
29+
name: corp/web-static-data
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
version: 1.1.0-beta1
2+
name: simple
3+
namespace: acmecorp
4+
description: "new fancy webapp with microservices"
5+
maintainers:
6+
- name: John Developer
7+
email: john.dev@acmecorp.cool
8+
- name: Jane Developer
9+
email: jane.dev@acmecorp.cool
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
versions:
2+
python: '3.6'
3+
postgres: '9.3'
4+
nginx: latest
5+
web_port: '8082'
6+
api_host: coolapp.com
7+
static_subdir: data/static
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
version: 1.1.0-beta1
2+
name: simple
3+
description: new fancy webapp with microservices
4+
namespace: ""
5+
maintainers:
6+
- name: Remilia Scarlet
7+
email: remilia@acmecorp.cool
8+
parents:
9+
- name: simple
10+
namespace: acmecorp
11+
version: 1.1.0-beta1
12+
maintainers:
13+
- name: John Developer
14+
email: john.dev@acmecorp.cool
15+
- name: Jane Developer
16+
email: jane.dev@acmecorp.cool
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
version: 1.1.0-beta1
2+
name: scarlet.devil
3+
description: new fancy webapp with microservices
4+
namespace: acmecorp
5+
maintainers:
6+
- name: Remilia Scarlet
7+
email: remilia@acmecorp.cool
8+
parents:
9+
- name: simple
10+
namespace: acmecorp
11+
version: 1.1.0-beta1
12+
maintainers:
13+
- name: John Developer
14+
email: john.dev@acmecorp.cool
15+
- name: Jane Developer
16+
email: jane.dev@acmecorp.cool

0 commit comments

Comments
 (0)