Skip to content
This repository has been archived by the owner on Oct 2, 2023. It is now read-only.

Add "entrypoint" to py_image rule #498

Closed
aymanrady opened this issue Aug 19, 2018 · 4 comments
Closed

Add "entrypoint" to py_image rule #498

aymanrady opened this issue Aug 19, 2018 · 4 comments

Comments

@aymanrady
Copy link

py_image assumes python is at /usr/bin/python, that's not always the case when changing the base image.
python:alpine from Docker hub has python at /usr/local/bin/python.

I'm affected by py_image & py3_image but I assume other lang rules are the same

maybe related #467

@nlopezgi
Copy link
Contributor

py_image does not make any assumptions, it just receives the python config info passed from Bazel (afaik, please correct my impression if you see otherwise after running tests with the flags indicated below).

You should be able to use python_top or python_path to inform Bazel where python is installed when you run the bazel command that will run your py_image rule. Please try these flags and let me know if they work for your use case, if not I will look into how to fix.

More about command line flags: https://docs.bazel.build/versions/master/command-line-reference.html
A longer discussion about current issues in these rules related to how Bazel does python: #490

@aymanrady
Copy link
Author

I ran bazel with python_path just to be sure, but that's not what I'm running into, my initial explanation wasn't detailed enough.

Description of the problem / feature request:

py_image hard codes container entrypoint to /usr/bin/python, we start running into problems when the base image doesn't have python at that location.

I'm working around this by patching rules_docker/python3:image.bzl

diff --git a/python3/image.bzl b/python3/image.bzl
index 1f1f178..9f7fa82 100644
--- a/python3/image.bzl
+++ b/python3/image.bzl
@@ -58,7 +58,9 @@ DEFAULT_BASE = select({
     "//conditions:default": "@py3_image_base//image",
 })
 
-def py3_image(name, base = None, deps = [], layers = [], **kwargs):
+DEFAULT_ENTRYPOINT = ["/usr/bin/python"]
+
+def py3_image(name, base = None, deps = [], layers = [], entrypoint = None, **kwargs):
     """Constructs a container image wrapping a py_binary target.
 
   Args:
@@ -89,7 +91,7 @@ def py3_image(name, base = None, deps = [], layers = [], **kwargs):
     app_layer(
         name = name,
         base = base,
-        entrypoint = ["/usr/bin/python"],
+        entrypoint = entrypoint or DEFAULT_ENTRYPOINT,
         binary = binary_name,
         lang_layers = layers,
         visibility = visibility,

I'm not sure this is the best solution, Inheriting entrypoint from the base image is probably better but I don't know how to go about it

Bugs: what's the simplest, easiest way to reproduce this bug? Please provide a minimal example if possible.

WORKSPACE

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

http_archive(
    name = "io_bazel_rules_docker",
    urls = ["https://github.com/bazelbuild/rules_docker/archive/d6046608f4979ad891a8c0574dd07ca7bf5f870e.tar.gz"],
    sha256 = "6872b8b0b509c6c3fcc3876f9b009b1984d9c5de80f9234dd6bfb8d8c504f314",
    strip_prefix = "rules_docker-d6046608f4979ad891a8c0574dd07ca7bf5f870e",
)

load("@io_bazel_rules_docker//python3:image.bzl", py3_container_repositories = "repositories")
py3_container_repositories()

load("@io_bazel_rules_docker//container:container.bzl", "container_pull")
container_pull(
    name = "python_cp37_image_base",
    registry = "index.docker.io",
    repository = "library/python",
    tag = "3.7.0-alpine3.8",
)

BUILD.bazel

load("@io_bazel_rules_docker//python3:image.bzl", "py3_image")

# This works, because distroless:python3 image has python at /usr/bin/python
py3_image(
    name = "distroless",
    srcs = ["bin.py"],
    main = "bin.py",
)

# This doesn't work, python is /usr/local/bin/python
py3_image(
    name = "alpine",
    base = "@python_cp37_image_base//image",
    srcs = ["bin.py"],
    main = "bin.py",
    # We need this to make it work
    # entrypoint = ["/usr/local/bin/python"],
)

Any other information, logs, or outputs that you want to share?

bazel run //:alpine

INFO: Analysed target //:alpine (1 packages loaded).
INFO: Found 1 target...
Target //:alpine up-to-date:
  bazel-bin/alpine-layer.tar
INFO: Elapsed time: 62.295s, Critical Path: 1.29s
INFO: 14 processes: 14 linux-sandbox.
INFO: Build completed successfully, 25 total actions
INFO: Build completed successfully, 25 total actions
02a69b79c8d7: Loading layer [==================================================>]  20.48kB/20.48kB
Loaded image ID: sha256:d1ff06c970108137da61102252593583f5f51deab77da8769616ae82581224f3
Tagging d1ff06c970108137da61102252593583f5f51deab77da8769616ae82581224f3 as bazel:alpine
docker: Error response from daemon: OCI runtime create failed: container_linux.go:348: starting container process caused "exec: \"/usr/bin/python\": stat /usr/bin/python: no such file or directory": unknown.

@nlopezgi
Copy link
Contributor

Thanks for the additional explanation.
Could you try to add a symlink to the base?

container_image(
  name = "base_with_py_symlink",
  base = "@python_cp37_image_base//image",
   symlinks = { "/usr/bin/python": "/usr/local/bin/python"},
)

py3_image(
    name = "alpine",
    base = "base_with_py_symlink",
    srcs = ["bin.py"],
    main = "bin.py",
)

We want to maintain sync between xx_binary and xx_image rules, so adding entrypoint to these rules is not an option. Let me know if the suggestion above works, otherwise I can think of other options.
Note the main problem here is that Bazel does not expose python runtime info to rules properly, which would be the right place to get this information from.

@nlopezgi
Copy link
Contributor

nlopezgi commented Dec 4, 2018

closing this issue as it should be possible to fix via adding the symlink, please let me know if you want to reopen (and suggest an alternative path if possible)

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

No branches or pull requests

2 participants