Fix problems under Docker. It would seem, what does GIT have to do with it?



Docker under Windows is an ongoing adventure. Then he needs to update the OS, otherwise the latest versions are not installed, then he forgets how to connect to the network. In general, every day from him news. “Set and forget” is not about Docker Desktop for Windows. Especially when it is not used exactly as its developers recommend. And for some reason they do not approve of connecting external windows to network drives as local. And they do not approve of access to network folders that are also located on the host machine. They write that this is horror-horror from a security point of view, they require all sorts of keys such as: for the mount command to work in the container, and so on and so forth.

cap_add:
- SYS_ADMIN
- DAC_READ_SEARCH




In general, when once again after the containers were uploaded to the customer’s server, the services stopped seeing network drives, I was not particularly surprised. This has already happened, and even a step-by-step instruction was written for the support group, how and what to reboot when the docker network settings break.

So I open my instructions and take action. Restarting containers does not help. I restart through docker-compose with recreation of an infrastructure - does not help. I reset the Docker settings to the factory settings, restore the settings for the virtual machine, reload the images, run through docker-compose - again, everything is as before - it does not see the network. More precisely, it does not connect to network balls, although ping from the container to the SMB server is normal. The last point is to reboot the server and reinstall Docker, while I skip, because I really do not want to restart the server. On this instruction ended.

Ok, I’m moving to my home machine, here I also have Docker for Windows, but a slightly newer version. I check on it. The same eggs:

There is no connection, but you hold on!

Yeah. Well, really, I think Docker rolled up the update with some kind of security and now my scripts do not start because of this? The last check is to completely remove Docker from the machine, and reinstall it. This should be cooler than resetting to factory settings. I’m doing the whole list from the previous step, only in addition to this I’m also restarting my car so that it’s completely ironic. I put Docker from scratch, upload images, launch docker-compose - eprst! All services both did not see the network ball and continue to write “mount error (22): Invalid argument” when loading.

I try to run the script line by line from the command line: connect to the container, run commands in turn and see that everything connects and works like need to:

mkdir -p $SMB_MOUNT_POINT
mount -t cifs $SMB_SHARE $SMB_MOUNT_POINT -o user=$SMB_USER,password=$SMB_PASSWORD,vers=2.0
ls $SMB_MOUNT_POINT

That is, what is this, some kind of crap with passing parameters to the script when the container starts?

We are looking for more ideas. All options with a docker reboot are shallow, there are options with possible changes in the parent image. My image is built based on openjdk: 8-jdk-alpine , no specific version is specified, so any security improvements could break my scripts. Maybe they changed something in OpenJDK or a subsidiary of Alpine?

I check the project logs, try to select the older openjdk: 8-jdk-alpine-3.8, openjdk: 8-jdk-alpine-3.7, etc. - every time I rebuild the container, check - everything is as before.

Damn it! Maybe I still changed something in my assembly? Unloading from GIT'a version of the project a month ago, collecting - the same glitches. Three months ago - the problem is still there. How so? What changed? The docker configuration is currently guaranteed to work, the image configuration has not changed either, the project sources are the same (GIT saves everything). There are no miracles - you need to understand where the changes nevertheless appeared. In prod, I manually launch the connection commands to the balls - so until the restart the services will work fine and go to sleep. The morning is wiser than the evening.

There is no connection, but you hold on!

The next morning the idea comes - that it’s probably time to find out, and what exactly the script does not like when executing.

The message “mount error (22): Invalid argument” is not very informative. I find that there is a magic key for the bash with which it displays debugging info when executing scripts.

Start debugging inside sh:

/ # sh -x /entry-point.sh
' echo 'Mount //<private_ip>/Exchange/Pipeline to /pipeline
Mount //<private_ip>/Exchange/Pipeline to /pipeline
' mkdir -p '/pipeline
' mount -t cifs //<private_ip>/Exchange/Pipeline /pipeline -o 'user=<private_user>,password=<private_password>,vers=2.0
mount error(22): Invalid argument
Refer to the mount.cifs(8) manual page (e.g. man mount.cifs)
mount: mounting //<private_ip>/Exchange/Pipeline on /pipeline failed: Invalid argument
' ls '/pipeline
+ exec

And here some strange moments appear - the line starts with quotation marks, then the quotation marks at the end ... Where are the quotation marks from?

Idea - can launching using real bash be more informative?

Install in the BASH container:

apk add bash

I start debugging:

/ # bash -x /entry-point.sh
' echo 'Mount //<private_ip>/Exchange/Pipeline to /pipeline
Mount //<private_ip>/Exchange/Pipeline to /pipeline
+ mkdir -p $'/pipeline\r'
+ mount -t cifs //<private_ip>/Exchange/Pipeline /pipeline -o $'user=<private_user>,password=<private_password>,vers=2.0\r'
mount error(22): Invalid argument
Refer to the mount.cifs(8) manual page (e.g. man mount.cifs)
mount: mounting //<private_ip>/Exchange/Pipeline on /pipeline failed: Invalid argument
+ ls $'/pipeline\r'
+ exec

Damn, it seems like when the line starts with a plus - it's good, but some kind of \ r and $ '...' options appeared .

We set Midnight Commander to experiment with amenities apk add mcand open the script for editing, and there:



Oppa! ^ M at the end of each line. Well, well, look at the local project - what about the line endings ???? CRLF. We work under Windows, however.

Change in this specific CRLF file to LF (long live Notepad ++!), Collect the project - bingo! It works as it should.

Why was it ok before, but now everything has flown? I look at the commits - there were no changes. And then I remember that GIT can edit linefeeds on the flytext files. And the other day I connected a new repository, and possibly uploaded all the files from there with conversion to CRLF.

As a result, we add the .gitattributes file to the project , indicating that in separate files it is necessary to save the end of line characters as in UNIX:

# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto

# Declare files that will always have LF line endings on checkout.
*.sh text eol=lf

Morality - sometimes the culprit does not even fall into the circle of initial suspects.

P.S


After updating to the latest version of Docker Desktop for Windows 2.2.0.3, everything stopped working back. This time, I immediately went inside the containers, and started debugging. It turned out that the 10.0.75.1 IP address for accessing the host machine stopped working, DockerNat is now removed from the system, and the DockerDesktopVM virtual machine does not even have an external network adapter, i.e. communication with it does not go through a standard network, but somehow differently. And to access the host, you must use host.docker.internal . Fellow developers and wrote that
DockerNAT has been removed from Docker Desktop 2.2.0.0 as using an IP address to communicate from the host to a container is not a supported feature. To communicate from a container to the host, you must use the special DNS name host.docker.internal.

Ok, I fixed the configs for the test environment, the database picked up, ping from the container to host.docker.internal passes, but the network drives are not connected. I try to run mount manually from the shell, and I get the familiar error “mount error (22): Invalid argument”.

I remove the arguments in turn - I just run “mount -t cifs //host.docker.internal/playground / pipeline” - it seems to work, but it’s knocking from the root user.

Add user: mount -t cifs //host.docker.internal/playground / pipeline -o user = smbuser - asks for a password and connects!

The full version also works:

mount -t cifs //host.docker.internal/playground /pipeline -o user=smbuser,password=smbpassword

but " mount -t cifs //host.docker.internal/playground / pipeline -o user = smbuser, password = smbpassword, vers = 2.0 " does not plow.

I change the last parameter to vers = 2.1 - cheers, it works!

It seems that Docker in its latest version made its own implementation of the SMB server with blackjack, but without 2.0 support. Nonsense, of course, compared to other news.

All goodness, strength and perseverance!

The illustration for the article was taken from blog.eduonix.com/software-development/learn-debug-docker-containers

All Articles