How to locate the Cargo.lock from build.rs - rust-cargo

I want to be able to read the Cargo.lock file from build.rs without resorting to literal paths.
In build.rs, std::env::var("CARGO_MANIFEST_DIR").unwrap(); can be used to find the Cargo.toml, and traditionally the Cargo.lock was in this directory, however with the introduction of workspaces that is no longer always true.

https://crates.io/crates/project-root can be used to find the nearest Cargo.lock up the directory structure from the current directory.
In Cargo.toml add
[build-dependencies]
project-root = "*"
And in build.rs use project_root::get_project_root().unwrap() to obtain the directory where Cargo.lock is.
(It would be nice to find a solution which doesn't need additional dependencies)

Related

Using Docker COPY to copy files to container without keeping directory structure

Starting to use Docker here.
Right now im facing an issue with my project, where I need to copy multiple files from multiple directories to the docker image on start up.
Here is my current code
FROM heroiclabs/nakama:3.11.0
COPY src/*.lua /nakama/data/modules
COPY src/database/*.lua /nakama/data/modules
COPY src/managers/*.lua /nakama/data/modules
COPY src/modules/*.lua /nakama/data/modules
COPY local.yml /nakama/data
What is happening so far is that docker copies only the main.lua file from the starting directory, it either dont copy the remaining ones or copy them with the current data structure.
How can I actually copy it in order to get the lua files from database, manages and modules into the same root directory as main.lua?
To add to this, I get this error on the Nakama console that indicates that a file searched by main.lua module its not found.
{"level":"fatal","ts":"2022-04-28T21:19:51.163Z","caller":"main.go:154","msg":"Failed initializing runtime modules","error":"/nakama/data/modules/src/main.lua:2: module economyManager not found:\n\tno field package.preload['economyManager']\n\tno cached module 'economyManager', \nstack traceback:\n\t[G]: in function 'require'\n\t/nakama/data/modules/src/main.lua:2: in main chunk\n\t[G]: ?"}
So far so good, the / at the end of each COPY line did not do the trick.
Edit:
This is the full directory structure:
src
-database
--luascripts.lua
-managers
--luascripts.lua
-modules
--luascripts.lua
-main.lua
intellisense
-nakama.lua
local.yml
dorckerfile
docker-compose.yml
This helps better illustrate the error. As you can se on the log, docker its copying src directory over to nakama/data/modules, what I aim to do is to copy ONLY the content from src, but not the src directory.
Same can be said for other directories to a lesser degree, my aim is to not carry over directory structure to the destination path
Your command seems to be right, just add a trailing / to the destination docker image's path.
For example,
COPY *.lua /nakama/data/modules/
The error was on the docker-compose file, I was double mounting a volume and that was causing errors on the whole COPY operation.

Copy directory into docker build no matter if empty or not - fails on "COPY failed: no source files were specified"

I have directory csv in context directory of docker build. I want to copy it into docker image in all circumstances (for empty directory in host an empty directory inside image is created, for nonempty directory in host it is copied with all content).
The COPY csv/* /csv/ gives COPY failed: no source files were specified error when the directory is empty.
Similar questions I found on SO are differing from my case in either setup or intention (multistage build, copying existing jar, certainly existing file) so I choose Q&A-style here rather than messing question with unrelated answer. This Github issue is also related.
The solution is to use
COPY csv/. /csv/
This question gave me a hint (although the behavior desired by me is unwanted for its OP).

How to copy multiple directories into a single directory and preserve directory structure

I would like to copy multiple directories (with contents) to a single directory in my container while maintaining the original directory structure of my project. For example, the relevant line in my Dockerfile looks like this:
COPY bin env project ./projects/
The command above only copies files into my projects directory and also removes all of the original directory structure of bin, env, and project.
How can I copy several directories (with contents) such that the original directory structures are preserved? I did find this reference, but as the first commenter points out, directory structure is lost with this method.
you need to create the directory structure since COPY will only add files not the directory itself.
one approach will be aading them one by one.
RUN mkdir -p projects/{bin,env,project}
COPY bin projects/
COPY env projects/
COPY project projects/
or maybe using ADD will be a better approach since Add will decompress archives download files and more.
so you will need to archive directories first, then use add like below
ADD archive.tgz projects/

How to copy multiple files in different source and destination directories using a single COPY layer in Dockerfile

I have a Dockerfile that looks like this:
COPY ./aaa/package.json ./aaa/package.json
COPY ./bbb/package.json ./bbb/package.json
COPY ./ccc/package.json ./ccc/package.json
WORKDIR aaa
RUN npm install
COPY ./aaa ./aaa
Basically module aaa uses bbb and ccc as local npm modules
Is it possible to write it so that the first 3 COPY instructions are done with a single COPY instruction so that they are 1 layer instead of 3? (I realize there's a 4th layer with the last COPY)
I still need the last COPY separate. That's intentional. The reason for splitting out the last layer is that the npm install is only dependent on the package.json files, and this way if I change source code, it doesn't need to rebuild all layers, just the last one. Only if I change the package.json files does it need to rebuild the first layer and do a new npm install. This was a fine pattern for me using a single module, but now that I've got a main module that is using local submodules (local npm modules) I'm stuck on how to reduce the number of COPY instructions to reduce the number of layers. A full description of this technique is documented (and recommended) at nodejs.org in the article "Dockerizing a Node.js web app"
Worth mentioning that it technically works as is, but it's inefficient because it creates extra layers for the extra copies when it seems like it should be possible to somehow get the first three COPY instructions combined to get one layer.
You're trying to convert this to a many-to-many copy. This isn't supported by the Dockerfile syntax. You need to have a single destination directory on the right side. And if your source is one or more directories, you need to be aware that docker will copy the contents of those directories, not the directory name itself. The result is that you want:
COPY json-files/ ./
And then you need to organize your build context (in docker build . the . or current directory is your build context that is sent to the docker server to perform the build) with a directory called json-files (could be any name) that contains only the files in the directory structure you want to copy:
| json-files/
|- aaa/package.json
|- bbb/package.json
\- ccc/package.json
Option 2:
You could structure your build as a multi-stage build to get this down to a single layer without modifying your build context itself:
FROM scratch as json-files
COPY ./aaa/package.json /json-files/aaa/package.json
COPY ./bbb/package.json /json-files/bbb/package.json
COPY ./ccc/package.json /json-files/ccc/package.json
FROM your_base
COPY --from=json-files /json-files .
WORKDIR aaa
RUN npm install
COPY ./aaa ./aaa
This second option is the same as the first from the the view of your COPY command, it just has an image as it's context instead of the build context sent over with the build command.
All this said, changing from 3 copy commands to 1, for small individual files that do not overwrite each other, is unlikely to have any noticeable impact on your performance and this looks like premature optimization.

Why is my dockerfile not copying directories

in my dockerfile I have these two lines:
ADD /ansible/inventory /etc/ansible/hosts
ADD /ansible/. /ansiblerepo
The first line works, as I can run the container and see my hosts file has been populated with all the ips from my inventory file.
The second line doesn't appear to be working though. I'm just trying to copy all the files/subdirectories of ansible and copy them over to the ansiblerepo directory inside the new container.
There are no errors while building the image, but again ansiblerepo is just an empty directory and nothing has copied over to it. I assume I'm just missing a back slash or something.
Docker ADD and COPY commands work relative to the build directly, and only for files in that directory that weren't excluded with a .dockerignore file. The reason for this is that builds actually run on the docker host, which may be a remote machine. The first step of a docker build . is to package up all the files in the directory (in this case .) and send them to the host to run your build. Any absolute paths you provide are interpreted as relative to the build directory and anything you reference that wasn't sent to the server will be interpreted as a missing file.
The solution is to copy /ansible to your build directory (typically the same folder as your Dockerfile).
Make sure that in your ".dockerignore" file, it does not excluded everything. usually, dockerignore file has these lines
*
!obj\Docker\publish\*
!obj\Docker\empty\
this means that everything is ignored except publish and empty folders.
Removing trailing /. from source directory should fix the ADD command.
On a related note, Docker Best Practices suggest using COPY over ADD if you don't need the URL download feature.

Resources