Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: docker-entrypoint.sh file handling, closes #1456 #1579

Merged
merged 4 commits into from
Oct 22, 2021

Conversation

MasonM
Copy link
Contributor

@MasonM MasonM commented Oct 17, 2021

Description

The docker-entrypoint.sh script added in #1043 is intended to run the supplied command with node if it contains a - or doesn't correspond to a system command. In Alpine, this doesn't work if the supplied command corresponds to a regular, non-executable JS file.

The root issue is a bug in ash/dash: its implementation of command -v <command_name> incorrectly outputs the supplied command_name even for non-executable files. This is a violation of the POSIX standard and has been reported to the Debian team, though there's been no activity in several years.

As a workaround, this adds an additional check to docker-entrypoint.sh for regular files that aren't marked as executable.

Motivation and Context

See #1456

Testing Details

$ cd 14/alpine3.14
$ mkdir dist && echo 'console.log("success")' > dist/index.js                                                                                                              
$ docker run --rm -v "$PWD:/app" -w /app node:alpine3.14 dist/index.js                                                                                                
/usr/local/bin/docker-entrypoint.sh: exec: line 8: dist/index.js: Permission denied

$ docker build -t testimage . > /dev/null
$ docker run --rm -v "$PWD:/app" -w /app testimage dist/index.js                                                                                                           
success                                                           

Example Output(if appropriate)

N/A

Types of changes

  • Documentation
  • Version change (Update, remove or add more Node.js versions)
  • Variant change (Update, remove or add more variants, or versions of variants)
  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Others (non of above)

Checklist

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING.md document.
  • All new and existing tests passed. (I don't see any tests in this repository)

The docker-entrypoint.sh script added in
nodejs#1039 is intended to run the
supplied command with "node" if it contains a "-" or doesn't correspond
to a system command. In Alpine, this doesn't work if the supplied
command corresponds to a regular, non-executable JS file.

The root issue is a bug in ash/dash: its implementation of "command -v"
incorrectly outputs the supplied command_name even for non-executable
files. This is a violation of the POSIX standard and has been reported
to the Debian team in
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264, though there's
been no activity in several years.

As a workaround, this adds an additional check to docker-entrypoint.sh
for regular files that aren't marked as executable.
@MasonM MasonM force-pushed the fix-permission-denied branch from e29935e to 3101ce6 Compare October 17, 2021 23:11
@MasonM MasonM changed the title Fix docker-entrypoint.sh file handling, closes #1456 fix: docker-entrypoint.sh file handling, closes #1456 Oct 17, 2021
@MasonM MasonM marked this pull request as ready for review October 17, 2021 23:12
@SimenB
Copy link
Member

SimenB commented Oct 18, 2021

We have a couple of smoke tests (just running node -v, npm -v and yarn -v to ensure the binaries are there) - should we have that for the entrypoint as well? Our current scripts run inside image when its built, so it might not be as straight forward, tho

@SimenB SimenB requested a review from a team October 18, 2021 05:25
@MasonM
Copy link
Contributor Author

MasonM commented Oct 19, 2021

@SimenB Okay, I added a simple regression test to .github/workflows/build-test.yml, though this could lead to maintenance difficulties as that file grows. Having a test runner that can be invoked from the command line (e.g. https://github.com/docker-library/official-images/tree/master/test) seems ideal to me, but that would be quite a bit of work.

@@ -82,6 +82,14 @@ jobs:
echo "Expected: \"${{ matrix.version }}\", Got: \"${image_node_version}\""
[ "${image_node_version}" == "${{ matrix.version }}" ]

- name: Regression test for issue 1456
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if it's a good naming, maybe something more meaningful will be great.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I renamed it to "Verify entrypoint runs regular, non-executable files with node" and slightly simplified it

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, thanks @MasonM

@MasonM MasonM force-pushed the fix-permission-denied branch from 9cc6cfb to f89451f Compare October 20, 2021 01:41
@MasonM
Copy link
Contributor Author

MasonM commented Oct 20, 2021

@SimenB I did some research to see if there was a better way of writing tests, and I found #802, which added BATS to this repo. With BATS, the test I added to .github/workflows/build-test.yml would look something like:

setup() {
  tmp_file=$(mktemp)
  echo 'console.log("success")' > "${tmp_file}"
}

@test "Verify entrypoint runs regular, non-executable files with node" {
  run docker run --rm -v "${tmp_file}:/app/index.js" node:${{ matrix.version }}-${{ matrix.variant }} app/index.js
  [ "$output" = 'success' ]
}

That's cleaner IMO and would make it easy to add additional test cases, but BATS was removed in #1339. I think it should be brought back, though it probably should be in a separate PR to keep this one focused. What do you think?

@SimenB
Copy link
Member

SimenB commented Oct 20, 2021

Should be fine to re-add? /cc @nodejs/docker

@PeterDaveHello
Copy link
Member

Should be fine to re-add? /cc @nodejs/docker

I'm good to add it back 👍

@SimenB
Copy link
Member

SimenB commented Oct 20, 2021

Getting the test in would be great also beyond this specific issue, as it would have caught #1582 as well (at least I think so)

@MasonM
Copy link
Contributor Author

MasonM commented Oct 20, 2021

Okay, I'll work on adding back BATS and integrating it with Github Actions after this is merged.

edit: Here's a draft: #1588

@SimenB SimenB merged commit cbbf60d into nodejs:main Oct 22, 2021
@SimenB
Copy link
Member

SimenB commented Oct 22, 2021

Thanks @MasonM!

@github-actions
Copy link

Created PR on the official-images repo (docker-library/official-images#11157). See https://github.com/docker-library/faq#an-images-source-changed-in-git-now-what if you are wondering when it will be available on the Docker Hub.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants