diff --git a/docs/configuration/environment-variables.md b/docs/configuration/environment-variables.md index ebe7f511c..839883ee6 100644 --- a/docs/configuration/environment-variables.md +++ b/docs/configuration/environment-variables.md @@ -110,9 +110,7 @@ The following config variables have special meanings and can be set in a variety | `DOKKU_DISABLE_ANSI_PREFIX_REMOVAL` | none | `dokku config:set`
`/etc/environment`
`~dokku/.dokkurc`
`~dokku/.dokkurc/*` | Disables removal of the ANSI prefix during deploys. Can be used in cases where the client deployer does not understand ansi escape codes. | | `DOKKU_DISABLE_APP_AUTOCREATION` | none | `dokku config:set` | Disables automatic creation of a non-existent app on deploy. | | `DOKKU_DOCKER_STOP_TIMEOUT` | `10` | `dokku config:set` | Configurable grace period given to the `docker stop` command. If a container has not stopped by this time, a `kill -9` signal or equivalent is sent in order to force-terminate the container. Both the `ps:stop` and `apps:destroy` commands _also_ respect this value. If not specified, the docker defaults for the [docker stop command](https://docs.docker.com/engine/reference/commandline/stop/) will be used.| -| `DOKKU_DOCKERFILE_CMD` | dockerfile cmd | `dokku config:set` | | | `DOKKU_DOCKERFILE_CACHE_BUILD` | none | `dokku config:set` | | -| `DOKKU_DOCKERFILE_ENTRYPOINT` | dockerfile entrypoint | `dokku config:set` | | | `DOKKU_DOCKERFILE_PORTS` | dockerfile ports | `dokku config:set` | | | `DOKKU_DOCKERFILE_START_CMD` | none | `dokku config:set` | | | `DOKKU_PARALLEL_ARGUMENTS`. | none | `dokku config:set` | Allows passing custom arguments to parallel for `ps:*all` commands | diff --git a/docs/deployment/methods/buildpacks.md b/docs/deployment/methods/buildpacks.md index 728dd0d38..5a64f58e9 100644 --- a/docs/deployment/methods/buildpacks.md +++ b/docs/deployment/methods/buildpacks.md @@ -164,7 +164,7 @@ dokku buildpacks:report node-js-app --buildpacks-list If an application was previously deployed via Dockerfile, the following commands should be run before a buildpack deploy will succeed: ```shell -dokku config:unset --no-restart node-js-app DOKKU_DOCKERFILE_CMD DOKKU_DOCKERFILE_ENTRYPOINT DOKKU_PROXY_PORT_MAP +dokku config:unset --no-restart node-js-app DOKKU_PROXY_PORT_MAP ``` ### Using a specific buildpack version diff --git a/plugins/app-json/appjson.go b/plugins/app-json/appjson.go index fba7ae836..03be530b6 100644 --- a/plugins/app-json/appjson.go +++ b/plugins/app-json/appjson.go @@ -195,18 +195,12 @@ func executeScript(appName string, imageTag string, phase string) error { commitArgs := []string{"container", "commit"} if !isHerokuishImage { - dockerfileEntrypoint, _ := common.ConfigGet(appName, "DOKKU_DOCKERFILE_CMD", "") - if dockerfileEntrypoint == "" { - dockerfileEntrypoint, _ = getEntrypointFromImage(image) - } + dockerfileEntrypoint, _ := getEntrypointFromImage(image) if dockerfileEntrypoint != "" { commitArgs = append(commitArgs, "--change", dockerfileEntrypoint) } - dockerfileCommand, _ := common.ConfigGet(appName, "DOKKU_DOCKERFILE_CMD", "") - if dockerfileCommand == "" { - dockerfileCommand, _ = getCommandFromImage(image) - } + dockerfileCommand, _ := getCommandFromImage(image) if dockerfileCommand != "" { commitArgs = append(commitArgs, "--change", dockerfileCommand) } @@ -236,21 +230,47 @@ func executeScript(appName string, imageTag string, phase string) error { } func getEntrypointFromImage(image string) (string, error) { - entrypoint, err := common.DockerInspect(image, "{{range .Config.Entrypoint}}{{.}} {{end}}") + output, err := common.DockerInspect(image, "{{json .Config.Entrypoint}}") if err != nil { return "", err } + if output == "null" { + return "", err + } - return fmt.Sprintf("ENTRYPOINT %s", entrypoint), err + var entrypoint []string + if err = json.Unmarshal([]byte(output), &entrypoint); err != nil { + return "", err + } + + if len(entrypoint) == 3 && entrypoint[0] == "/bin/sh" && entrypoint[1] == "-c" { + return fmt.Sprintf("ENTRYPOINT %s", entrypoint[2]), nil + } + + serializedEntrypoint, err := json.Marshal(entrypoint) + return fmt.Sprintf("ENTRYPOINT %s", string(serializedEntrypoint)), err } func getCommandFromImage(image string) (string, error) { - command, err := common.DockerInspect(image, "{{range .Config.Cmd}}{{.}} {{end}}") + output, err := common.DockerInspect(image, "{{json .Config.Cmd}}") if err != nil { return "", err } + if output == "null" { + return "", err + } - return fmt.Sprintf("CMD %s", strings.Replace(command, "/bin/sh -c", "", 1)), err + var command []string + if err = json.Unmarshal([]byte(output), &command); err != nil { + return "", err + } + + if len(command) == 3 && command[0] == "/bin/sh" && command[1] == "-c" { + return fmt.Sprintf("CMD %s", command[2]), nil + } + + serializedEntrypoint, err := json.Marshal(command) + return fmt.Sprintf("CMD %s", string(serializedEntrypoint)), err } func waitForExecution(containerID string) bool { diff --git a/plugins/builder-dockerfile/builder-build b/plugins/builder-dockerfile/builder-build index 2a1cf3f53..a443da29b 100755 --- a/plugins/builder-dockerfile/builder-build +++ b/plugins/builder-dockerfile/builder-build @@ -20,12 +20,6 @@ trigger-builder-dockerfile-builder-build() { # extract first port from Dockerfile local DOCKERFILE_PORTS=$(get_dockerfile_exposed_ports Dockerfile) [[ -n "$DOCKERFILE_PORTS" ]] && config_set --no-restart "$APP" DOKKU_DOCKERFILE_PORTS="$DOCKERFILE_PORTS" - - # extract ENTRYPOINT/CMD from Dockerfile - local DOCKERFILE_ENTRYPOINT=$(extract_directive_from_dockerfile Dockerfile ENTRYPOINT) - [[ -n "$DOCKERFILE_ENTRYPOINT" ]] && config_set --no-restart "$APP" DOKKU_DOCKERFILE_ENTRYPOINT="$DOCKERFILE_ENTRYPOINT" - local DOCKERFILE_CMD=$(extract_directive_from_dockerfile Dockerfile CMD) - [[ -n "$DOCKERFILE_CMD" ]] && config_set --no-restart "$APP" DOKKU_DOCKERFILE_CMD="$DOCKERFILE_CMD" plugn trigger pre-build-dockerfile "$APP" [[ "$DOKKU_DOCKERFILE_CACHE_BUILD" == "false" ]] && DOKKU_DOCKER_BUILD_OPTS="$DOKKU_DOCKER_BUILD_OPTS --no-cache" diff --git a/tests/apps/dockerfile-entrypoint/Dockerfile b/tests/apps/dockerfile-entrypoint/Dockerfile new file mode 100644 index 000000000..18d2ddaa5 --- /dev/null +++ b/tests/apps/dockerfile-entrypoint/Dockerfile @@ -0,0 +1,10 @@ +FROM ruby:2.5.1 + +RUN mkdir /app +WORKDIR /app + +ADD Procfile Procfile +ADD entrypoint entrypoint +ADD app.json app.json + +ENTRYPOINT ["./entrypoint"] diff --git a/tests/apps/dockerfile-entrypoint/Procfile b/tests/apps/dockerfile-entrypoint/Procfile new file mode 100644 index 000000000..f296d4a33 --- /dev/null +++ b/tests/apps/dockerfile-entrypoint/Procfile @@ -0,0 +1 @@ +web: sleep 1000 diff --git a/tests/apps/dockerfile-entrypoint/app.json b/tests/apps/dockerfile-entrypoint/app.json new file mode 100644 index 000000000..16b493cb2 --- /dev/null +++ b/tests/apps/dockerfile-entrypoint/app.json @@ -0,0 +1,7 @@ +{ + "scripts": { + "dokku": { + "predeploy": "touch /app/predeploy.test" + } + } +} diff --git a/tests/apps/dockerfile-entrypoint/entrypoint b/tests/apps/dockerfile-entrypoint/entrypoint new file mode 100755 index 000000000..9c2c70694 --- /dev/null +++ b/tests/apps/dockerfile-entrypoint/entrypoint @@ -0,0 +1,4 @@ +#!/bin/bash + +echo "entrypoint script started with arguments $@" +exec "$@" diff --git a/tests/apps/dockerfile-procfile/app.json b/tests/apps/dockerfile-procfile/app.json new file mode 100644 index 000000000..0dbdea3ec --- /dev/null +++ b/tests/apps/dockerfile-procfile/app.json @@ -0,0 +1,8 @@ +{ + "scripts": { + "dokku": { + "predeploy": "touch /app/predeploy.test", + "postdeploy": "touch /app/postdeploy.test" + } + } +} diff --git a/tests/unit/app-json.bats b/tests/unit/app-json.bats index 925f783d1..243f4fc83 100644 --- a/tests/unit/app-json.bats +++ b/tests/unit/app-json.bats @@ -18,6 +18,12 @@ teardown() { echo "status: $status" assert_success + run docker inspect "${TEST_APP}.web.1" --format "{{json .Config.Cmd}}" + echo "output: $output" + echo "status: $status" + assert_success + assert_output '["/start","web"]' + run /bin/bash -c "dokku --rm run $TEST_APP ls /app/prebuild.test" echo "output: $output" echo "status: $status" @@ -37,10 +43,47 @@ teardown() { assert_success } - @test "(app-json) app.json scripts missing" { deploy_app nodejs-express-noappjson echo "output: $output" echo "status: $status" assert_success } + +@test "(app-json) app.json dockerfile cmd" { + deploy_app dockerfile-procfile + echo "output: $output" + echo "status: $status" + assert_success + + run docker inspect "dokku/${TEST_APP}:latest" --format "{{json .Config.Cmd}}" + echo "output: $output" + echo "status: $status" + assert_success + assert_output '["/bin/sh","-c","npm start"]' + + run docker inspect "dokku/${TEST_APP}:latest" --format "{{json .Config.Entrypoint}}" + echo "output: $output" + echo "status: $status" + assert_success + assert_output 'null' +} + +@test "(app-json) app.json dockerfile entrypoint" { + deploy_app dockerfile-entrypoint + echo "output: $output" + echo "status: $status" + assert_success + + run docker inspect "dokku/${TEST_APP}:latest" --format "{{json .Config.Cmd}}" + echo "output: $output" + echo "status: $status" + assert_success + assert_output 'null' + + run docker inspect "dokku/${TEST_APP}:latest" --format "{{json .Config.Entrypoint}}" + echo "output: $output" + echo "status: $status" + assert_success + assert_output '["./entrypoint"]' +}