Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Node App Can't Read File System in Docker Image

Alright so I have a node app that access a directory in it's file structure and does stuff with it. I'm using the 'fs' module to accomplish this. When I run a container from its image, I get the following error:

Error: ENOENT, readdir './classes/cs395'

I immediately thought of a whole bunch of things that could be wrong UNTIL I attached to the running container (after restarting it because the container will die upon error...of course). When I started the node app from inside the container..it worked..no errors.

I believe it might have something to do with the way file systems are handled when docker images are layered but when it worked fine when I attached to the container I became really confused

EDIT:

The file DOES exists...here's proof: enter image description here Again, if (as i'm attached to the container as shown in the picture) I run node server.js and ping the ip:port everything works great! the directory is recognized! But NOT if is run detached from the image.

To show that the file is still there, let's start our stopped container and attach to it...as you can see the file is still there. (Note that starting the container won't recreate the file it wasn't there when it stopped...it will just pick up where it left off) enter image description here

In case it helps, here is how I am using the 'fs' module:

var p = "./classes/cs395";

//READ ALL FILES FROM A DIRECTORY AND EMIT THE NAME OF THE FILE
fs.readdir(p, function(err, files){
    if (err) throw err;

    files.forEach(function (file) {
        if (files.length == 1 && file == '.DS_Store'){
            io.emit('receive_file', null);
        } else {
            fs.stat(p + '/' + file, function(err, stats){
                if (err) throw err;

                if (stats.isFile() && file != '.DS_Store'){
                    var ext = path.extname(file);
                    var name = path.basename(p + '/' + file, ext);
                    io.emit('receive_file', name);
                }
            });

        }
    });  

    if (files.length == 0) {
        io.emit('receive_file', null);
    }    

    console.log(files);
}); 
like image 637
frankgreco Avatar asked Feb 20 '16 00:02

frankgreco


2 Answers

The challenge is identifying the expected location of node script execution and the actual working directory in docker. This difference will account for discrepancies between what you expect the file path of "." to be and what it actually is.

The easiest way to determine if you are executing with the context you think you are is to console out the Fs.realpathSync(".") I would expect that the location is not where you thought you were executing from (but it should match with what your WORKDIR is set to in your Docker image). (You can also prove this is your problem by changing your "." paths to absolute ones temporarily.)

Change your working directory to point to where you expect your "." to be (in your case WORKDIR /src) and you should be able to use the "." the way you expect.

like image 122
purgatory101 Avatar answered Oct 18 '22 04:10

purgatory101


ENOENT means that there is no such directory entry; the file ./classes/cs395 doesn't exist and therefore fs can't read it. Check to see if it's there before and after.

See Why does ENOENT mean "No such file or directory"? for more info.

In that it's working once the app has restarted, one possibility is that the file is created once the app is first run, and you are trying to read it before it has been created.

like image 30
max_ Avatar answered Oct 18 '22 03:10

max_