Question about building a pex into a Docker image....
# general
b
Question about building a pex into a Docker image. I need to reference some files in my repo - the code does things like
shutil.copytree(src/services/app/static, etc)
. This works fine when I run the pex target, but once I build a Docker image from it I get
FileNotFoundError: [Errno 2] No such file or directory: 'src/services/app/static'
. I tried adding the directory as both a
files
and
resources
and having my docker target depend on it, but that didn't help. What's the magic I'm looking for here? Am I not referencing it right in the Docker image, or are those files not going to be there at all without some extra work? For reference, my dockerfile itself is simply
Copy code
FROM python:3.8
ENTRYPOINT ["/bin/app.pex"]
COPY src.services.app.scripts/app.pex /bin
c
did you also add a
COPY src/ src
to your Dockerfile? otherwise the files would be in the docker build context, but not available to your pex file when running in the container.
πŸ‘€ 1
may need to tweak the
/
in there.. I’ve not used Docker for along time, so don’t recall from the top of my head if it needs to be
COPY src src/
or
COPY src/ src/
or any other combo.. πŸ˜‰
b
src/ src
seemed to have worked, thank you very much!
πŸ’― 1
g
I am having a similar problem. My assets reside in
assets/
, docker in
src/python/service_name/Dockerfile,
and my pex has a dependency on the right assets. It doesn't seem like assets are getting copied automatically, and trying:
COPY /assets assets
in docker isn't working. Any ideas?
e
@glamorous-nail-59544 do you mean?:
Copy code
COPY assets/ assets
Note the `/`is in a different spot in my example than in yours and my example aligns with the conversation above.
g
I actually tried all combinations
does my repo structure make sense to docker context?
Copy code
src/python/services_name
src/python/services_name/dockerfile
3rdparty/python/reqs
assets/asset_name
I have default roots in pants.toml
e
The repo structure should be irrelevant in the end, Pants can work with most any layout.
my pex has a dependency on the right assets.
How do you spell the dependency? For the files to live in the PEX the dependency must be on a
resources
target and not a `files`target - for not good reasons, but it's true today anyhow.
g
My file deps are automatically inferred from code, and verified that using
./pants dependencies --transitive.
And yes I am aware that they are not packaged in the pex, but I thought docker target will be smarter and copy them into the correct relative path.
e
So, can you answer my question though? Are the dependencies on resources targets or file targets?
g
file
e
Ok, would you mind trying a switch to resources then?
The steps would be change `files`to `resources`and then
./pants package the/pex:target
and then use zipinfo to inspect the PEX and make sure the files are in there.
That would be step 1.
g
I have a lib that requires some files and it is using
open
which I don't think works with resource? Also, something interesting, adding the assets dep explicitly worked!
Copy code
docker_image(name="service_name", source="Dockerfile", dependencies=["assets:files"])
e
It does work with resource
Ok
g
will give resource a try, but not sure why explicit dependency is required here!
e
How does Pants infer the dependency? Most dependency inference is via analysis of import statements. Surely you don't import these assets.
g
transitive deps without explicit declaration
Copy code
assets/DejaVuSansCondensed.ttf:files
assets/i18n/BUILD:files
assets/i18n/responses.en.yml:files
with explicit declaration
Copy code
assets/BUILD:files
assets/DejaVuSansCondensed.ttf:files
assets/cv.docx:files
assets/i18n/BUILD:files
assets/i18n/responses.en.yml:files
assets/test_image.jpg:files
I am using files cause this lib wasn't working with resource based assets
e
Ok, my question though was how that 1st set is being inferred. Generally Pants can only infer dependencies by following import statements. Presumably 0 of these lead to assets/*.
FWIW, that library can work with Pants
resources
targets. Something like this:
Copy code
import i18n
i18n.load_path.append(Path(__file__).parent.parent / "assets")
πŸ‘€ 1
g
I remember reading that it can do this and there is a config to define number of separators before pants tries to infer them, can't find where I read it! Will check the above
e
Don't be confused by `resources`being named "resources". You do not need to use
importlib.resources
- for example - to access files included via the Pants `resources`concept.
Coming next year most likely will be a collapsing of the
files
and
resources
targets into a single `assets`target to underscore this and hopefully confuse less people.
😍 1
But that is really just cosmetic - you can use resources today to access files and do it with open, etc.
You just need to figure out the path to the files based off some module's
__file__
.
g
Will play around more with
resource
target
e
Ok. Yeah - those sorts of infers are iffy and only work a small portion of the time in general.
g
They did pretty well with
files
target
e
The target type should not be relevant.
g
well, I mean using relative path, might work with
resources
as well, but as you mentioned above, if I use file I will loose he path which will make it hard to infer
e
Ah gotcha. I understand now. I personally would never use / rely on asset inference, but if you like using it, your issue with resources makes sense.
g
I love everything infer about pants, it feels magical this way. I would love to see this also be ported to docker build target if possible! Anyhow, thanks for the info, will examine using resources and evaluate which is better for my and my team's mental health πŸ™‚
well,
resources
are working well, the only gotcha is they don't get inferred, only files are. So I had to turn off
assets
inference and explicitly define my resources deps. I think automatically inferring resources as well would be really nice for a project structure like mine.
assets
will always be at root and importing them will always be the same weather my code is packaged or not. EDIT: looking forward to the
assets
target!
b
Asset inference is somewhat magical, but it is a necessary evil to have virtually no explicit dependencies, which is a much worse evil
e
That's definitely in the eye of the beholder.
b
So @glamorous-nail-59544 both resources and files are inferred, but they are inferred differently. Files are assumed to be loaded relative to build root (which is what you must be doing). Resources are assumed to be loaded relative to the file loading them (as if using importlib with
__name__
)
@enough-analyst-54434 it's certainly subjective, although I'd love you hear your viewpoint. For us, our employees aren't engineers, so they don't think in build systems. Having to declare dependencies is not something they are used to, especially for files on disk which are right there. The amount of "why did this test fail, the file exists" questions i got would fill your pocket with nickels. So asset inference not only keeps deps fresh, but also helps us with the "Pants helps us not think about build systems" we know and love
e
I am an engineer; so eye of the beholder as I said,. I'd never turn asset inference on. I also don't use the default source root magic for the same reason - I declare mine explicitly.
g
@bitter-ability-32190 my assets are in
assets
dir in the repo root. I couldn't find a way to load them using
importlib
or
pkgutil
, so can't get pants to infer them πŸ€·β€β™‚οΈ
b
Yeah those are likely best treated as "files"