2

I am trying to use a custom Dockerfile to build the LUIS container and copy the app file (app exported from the Luis portal) into the container. For this reason, I really don't need the mount points, since the .gz file will already live in the container. Is this possible? It seems that the mount points are always required...

I have to copy the files into the container and the move them to the input location at runtime (using an init.sh script). But, even then the container seemed to not load the app correctly. It behaves differently from that scenario compared to just putting the file in the host folder and mounting that to the container.

UPDATE: When I try to move the files around internally (at the start of the container), LUIS gives this output:

Using '/input' for reading models and other read-only data.
Using '/output/luis/fbfb798892fd' for writing logs and other output data.
Logging to console.
Submitting metering to 'https://southcentralus.api.cognitive.microsoft.com/'.
warn: Microsoft.AspNetCore.Server.Kestrel[0]
      Overriding address(es) 'http://+:80'. Binding to endpoints defined in UseKestrel() instead.
Hosting environment: Production
Content root path: /app
Now listening on: http://0.0.0.0:5000
Application started. Press Ctrl+C to shut down.
fail: Luis[0]
      Failed while prefetching App: AppId: d6fa5fd3-c32a-44d5-bb7f-d563775cf6ee - Slot: PRODUCTION Could not find file '/input/d6fa5fd3-c32a-44d5-bb7f-d563775cf6ee_PRODUCTION.gz'.
fail: Luis[0]
      Failed while getting response for AppId: d6fa5fd3-c32a-44d5-bb7f-d563775cf6ee - Slot: PRODUCTION. Error: Could not find file '/input/d6fa5fd3-c32a-44d5-bb7f-d563775cf6ee_PRODUCTION.gz'.
warn: Microsoft.CloudAI.Containers.Controllers.LuisControllerV3[0]
      Response status code: 404
      Exception: Could not find file '/input/d6fa5fd3-c32a-44d5-bb7f-d563775cf6ee_PRODUCTION.gz'. SubscriptionId='' RequestId='d7dfee25-05d9-4af6-804d-58558f55465e' Timestamp=''
^C
nuc@nuc-NUC8i7BEK:/tmp/input$ sudo docker exec -it luis bash
root@fbfb798892fd:/app# cd /input
root@fbfb798892fd:/input# ls
d6fa5fd3-c32a-44d5-bb7f-d563775cf6ee_production.gz
root@fbfb798892fd:/input# ls -l
total 8
-rwxrwxrwx 1 root root 4960 Dec  2 17:35 d6fa5fd3-c32a-44d5-bb7f-d563775cf6ee_production.gz
root@fbfb798892fd:/input# 

Notice that even though I can log into the container and browse the location of the model files and they are present, LUIS cannot load/find them.

UPDATE #2 - posting my Dockerfile:

FROM mcr.microsoft.com/azure-cognitive-services/luis:latest

ENV Eula=accept
ENV Billing=https://southcentralus.api.cognitive.microsoft.com/
ENV ApiKey=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
ENV Logging:Console:LogLevel:Default=Debug

RUN mkdir /app/inputfiles/
RUN chmod 777 /app/inputfiles/
COPY *.gz /app/inputfiles/

WORKDIR /app

COPY init.sh .
RUN chmod 777 /app/init.sh

ENTRYPOINT /app/init.sh && dotnet Microsoft.CloudAI.Containers.Luis.dll
runninggeek
  • 147
  • 2
  • 11
  • Are you saying you're trying to build your own version of the mcr.microsoft.com/azure-cognitive-services/luis image that includes your exported .gz file inside of it? What are you hoping to accomplish by doing this? – Kyle Delaney Nov 15 '19 at 23:44
  • Are you still working on this? – Kyle Delaney Nov 20 '19 at 23:10
  • There is no workaround for this issue that I have found. I would love to know a way around this constraint. But, I don't see one in the current container. So, yes, it's still an issue but I am submitting to the way it requires at this point. – runninggeek Nov 22 '19 at 03:29
  • That doesn't answer my questions though – Kyle Delaney Nov 22 '19 at 21:54
  • I was using my own Dockerfile, but it uses that image. I just wanted to build an image that included my exported files. I want to be able to hand this image off to someone else on my team with the only thing they have to do is build the image and not have to move files onto the host machine. – runninggeek Nov 23 '19 at 23:06
  • Are you still working on this? – Kyle Delaney Dec 02 '19 at 01:13
  • Linking: https://github.com/MicrosoftDocs/azure-docs/issues/42377 – Kyle Delaney Dec 02 '19 at 16:33
  • 1
    What does your `init.sh` file look like? Also, the container is referring to an */input* and your files are copied into */inputfiles* - is that concerning? – David Pine Dec 03 '19 at 18:53
  • 1
    @DavidPine - Yes, the .gz file needs to be copied to **/input** and not **/app/inputFiles** in order for this to work – Kyle Delaney Dec 03 '19 at 19:08

2 Answers2

1

It's true that the input mount won't be necessary if your .gz file is already in the image, but the output mount is used for logging and you may still want that for active learning purposes.

To build your desired image, create a text file named Dockerfile (no extension) and populate it with the following lines:

FROM mcr.microsoft.com/azure-cognitive-services/luis:latest

ENV Eula=accept
ENV Billing={ENDPOINT_URI}
ENV ApiKey={API_KEY}

COPY ./{luisAppId}_PRODUCTION.gz /input/{luisAppId}_PRODUCTION.gz

You can find your {ENDPOINT_URI} and your {API_KEY} using the normal LUIS container instructions, and {luisAppId} will be found in the name of your .gz file of course. Once your Dockerfile is ready, run it from the same folder that contains your .gz file with this command:

docker build -t luis .

Your image will now be ready. All your teammate has to do is run this command:

docker run --rm -it -p 5000:5000
  --memory 4g
  --cpus 2
  --mount type=bind,src={OUTPUT_FOLDER},target=/output luis

{OUTPUT_FOLDER} can be any local absolute path you want as long as it exists. You may also omit the output mount if you don't want any logging:

docker run --rm -it -p 5000:5000 --memory 4g --cpus 2 luis
Kyle Delaney
  • 11,616
  • 6
  • 39
  • 66
  • Yes - I already tried that. It doesn’t work. Btw, I am only asking that the mount points be made optional, but as it is right now, they are required. The reason, and the reason your solution won’t work, is that when you copy the files using the dockerfile, that’s at build time. The mount point happens at runtime. The mount point overrides the internal files that were copied at buildtime. Furthermore, I even tested a solution that ran at runtime and copied the files once the container started. That also doesn’t work. The only solution that works is the mount point. – runninggeek Nov 27 '19 at 01:11
  • @runninggeek - When you ask a question on Stack Overflow, you are supposed to provide a comprehensive explanation of what you've already tried – Kyle Delaney Nov 27 '19 at 02:28
  • @runninggeek - Can you explain what exactly "doesn't work" so that I may help you make it work? It would help if you edited your question to include the Dockerfile you made and the commands you're using to build it and run it. Both mount points are already optional, and I explained that I'm only including the output mount point for logging purposes. You can leave out both mount points if you wish, but you should definitely leave out the input mount point (like I've shown) because it only served to get the .gz file into the container's input folder, which the Dockerfile here already does. – Kyle Delaney Nov 27 '19 at 16:44
  • When I say "doesn't work", I mean the LUIS app does not load the model correctly. I'm not exactly sure what the issue is, but there is a difference in behavior when I place the files in the host folder vs trying to copy them around when the container starts. – runninggeek Dec 02 '19 at 17:28
  • See the updated output I posted in the original issue. It shows the behavior I get when I try to move the files around within the container. – runninggeek Dec 02 '19 at 17:47
  • @runninggeek - I don't understand what you mean when you keep talking about copying files when the container starts. The only time you need to copy files is when you build the image. While it's helpful to see the output you posted, would you mind sharing the contents of your Dockerfile as well? – Kyle Delaney Dec 02 '19 at 18:08
  • When you build the Docker image, you can only copy the LUIS model files to a specific dir in the container. But, the mount points don't get set until RUN TIME. The mounting of the dir that happens at run time overrides that internal dir in the container. So, any files in the dir are not seen/available by the container. To avoid that, I copy the files at run time, after the mount points have been set. So, the files get copied to a "holding" dir and then at startup, I copy the files to the right location. That's what I mean by moving the files around within the container. Does that make sense? – runninggeek Dec 02 '19 at 22:58
  • Just posted my dockerfile. – runninggeek Dec 02 '19 at 23:02
  • @runninggeek - No, that does not make sense because you don't need any mount points, like I've said. I don't understand why you're insisting on using a mount point since your whole question was about how to avoid using mount points. I can see that your Dockerfile does not copy anything to the /input folder that the LUIS container is depending on, which would be the only way you could avoid needing the input mount. Please try out the Dockerfile I've already provided in my answer and see if it works. – Kyle Delaney Dec 02 '19 at 23:50
  • When I try to avoid the "input" mount point, I get a message "A folder must be mounted at the location "/input" where models and other input data can be read." That's been my point this whole time - I don't want to have to include the mount points, but when I omit them, I get an error message. – runninggeek Dec 03 '19 at 18:06
  • @runninggeek - Did you try using my sample Dockerfile according to my instructions? – Kyle Delaney Dec 03 '19 at 18:58
  • Yes - I tested it using your dockerfile example – runninggeek Dec 03 '19 at 20:42
  • @runninggeek - I can see that your Dockerfile is missing the necessary functionality from my example. Can you post the actual Dockerfile that you're using that's based on my example and still generating the message `A folder must be mounted at the location "/input" where models and other input data can be read.`? – Kyle Delaney Dec 03 '19 at 21:16
  • I literally just copied your Dockerfile and built an image using that. Also, the missing functionality in my Dockerfile (copying the files to the /input dir) is in the init.sh script. Just so you're aware where that logic is. But right now, I'm just using the Dockerfile you gave me and only specifying the output mount point and I get the error I posted earlier. – runninggeek Dec 03 '19 at 21:37
  • @runninggeek - I'm sorry for the frustration, but you have to understand that this solution is working for other people so you'll have to provide more information if you want us to figure out why it isn't working for you. You cannot just copy my Dockerfile because it needs to be modified with your endpoint URI, your API key, and your app ID in two places. You don't need to tell us your API key of course, but can you verify that you made the changes correctly or provide the steps you went through to obtain the values? – Kyle Delaney Dec 03 '19 at 22:18
  • totally get it. I wasn't aware it was working without the input mount points for others. And, yes, I can obviously see where I needed to replace the placeholder tokens you put in the Dockerfile that needed to be replaced. I was born at night, but not last night. :-) Regardless, I have it working now. The issue is that when I copied the file to /input I did not put the trailing "/" after input, so it did not create the input dir, but a file called "input". The error I got lead me to think the input mount was required. Sorry for the confusion and thanks for the help. – runninggeek Dec 03 '19 at 23:32
1

Option 1

The models can be COPY'd directly into /input/. e.g.

FROM mcr.microsoft.com/azure-cognitive-services/luis:latest

COPY *.gz /input/

This will work, but requires that you don't mount to /input at runtime as it will squash the COPY'd files. The message "A folder must be mounted" is only logged if the /input directory does not exist.

 > docker build . -t luis --no-cache
Sending build context to Docker daemon  40.43MB
Step 1/2 : FROM aicpppe.azurecr.io/microsoft/cognitive-services-luis
 ---> df4e32e45b1e
Step 2/2 : COPY ./*.gz /input/
 ---> c5f41a9d8522
Successfully built c5f41a9d8522
Successfully tagged luis:latest

> docker run --rm -it -p 5000:5000 luis eula=accept billing=*** apikey=***
...
Using '/input' for reading models and other read-only data.
...
Application started. Press Ctrl+C to shut down.

Option 2

The configuration value Mounts:Input can be set to configure the input location.

This might be useful if you need your models to live in /app/inputfiles or if you need to mount to /input for another reason at runtime.

e.g.

FROM aicpppe.azurecr.io/microsoft/cognitive-services-luis

ENV Mounts:Input=/app/inputfiles
COPY ./*.gz /app/inputfiles/

This results in:

 > docker build . -t luis --no-cache
Sending build context to Docker daemon  40.43MB
Step 1/3 : FROM aicpppe.azurecr.io/microsoft/cognitive-services-luis
 ---> df4e32e45b1e
Step 2/3 : ENV Mounts:Input=/app/inputfiles
 ---> Running in b6029a2b54d0
Removing intermediate container b6029a2b54d0
 ---> cb9a4e06463b
Step 3/3 : COPY ./*.gz /app/inputfiles/
 ---> 9ab1dfaa36e7
Successfully built 9ab1dfaa36e7
Successfully tagged luis:latest

 > docker run --rm -it -p 5000:5000 luis eula=accept billing=*** apikey=***
...
Using '/app/inputfiles' for reading models and other read-only data.
...
Application started. Press Ctrl+C to shut down.