7

I'm creating a development setup for a web app with Docker. We have developers running in Windows, Mac, and Linux. Everyone will be using Linux containers, but there are still issues that only affect Windows users.

I'm not looking to run the application differently than production. Rather it's the tooling around the developer setup that needs to be different.

Is there a way to detect the Operating system of a Host from within a Docker container?

1
  • Seems like most of the answers address detecting -windows- :( I need to detect macOS! May 25, 2023 at 17:50

4 Answers 4

1

Do you really want to do this?

I know you're not happy with a frame challenge answer, but please bear with me.

The problems you're facing appear because running Linux-based Docker on Windows is a hack. Certainly you can run into Windows filesystem issues, but there may be other issues I'm not aware of.

Now, as I understand, you want to add platform-specific workarounds to your project to allow running it in a VM on Windows hosts. Based on my experience I would recommend avoiding this.

  1. Windows is not a target platform for your project. Adding solutions for Windows-specific issues introduces unnecessary complexity. Unnecessary complexity means increased maintenance cost and potential for bugs which would not occur otherwise.

  2. You'll very likely run into more issues caused by filesystem incompatibility which are not strictly project problems, but still add unnecessary hassle under Windows. For example git falls apart when someone makes case-only filename changes on case-sensitive filesystems (ie. Linux) and other person pulls those changes to a Windows machine.

The real solution would be to develop in environment as similar to intended as possible. That means - on actual Linux host or in a Linux VM. This will guarantee that developers don't waste time (and money) on issues that exist only on their development platform. It will also guarantee that they don't miss problems which don't manifest on Windows.

Your customer doesn't care if the product runs well in a Linux VM on Windows. Your developers have to be familiar with Linux anyway because you're targeting Linux as your sole platform. Do you really want to spend resources on problems that don't exist in real-world scenarios?

10
  • 2
    1. I need to go to where the developers are. They run windows so i need to make it work.
    – dovidweisz
    Aug 14, 2019 at 16:20
  • It's not really Windows. It's Docker-on-Linux-in-a-VM-on-Windows-with-not-completely-compatible-filesystem. That's not a reasonable production environment in my book. I understand that developers have their preferences, but they should also have common sense. (If that's still a non-answer for you, that's okay - it's just what I figured out after fighting with this issue for too long.)
    – gronostaj
    Aug 14, 2019 at 16:24
  • 3
    I AM running them in another container. I just want to install the hook in this way for windows users. -- the hook starts the container :O
    – dovidweisz
    Aug 14, 2019 at 16:32
  • 2
    @gronostaj: I don't want to ague with you on this but see, we don't have to use linux to develop a linux software. "is it really worth to support Windows if your target platform is Linux" - yes it is, development environment is not always as powerful as deploy environment. And we can deploy docker on windows hosts, too. Just because people don't often do that doesn't mean that they don't do that at all. Back to the problem, docker is just a SW like other SW, it can easily get its running environment. We just want to know if somehow we can get that info from the docker or not.
    – Han
    Apr 16, 2020 at 3:04
  • 2
    I agree with @Han: this is not useful. It does not answer the question at all. And yes there are plenty of real world scenarios, e.g. when developing for Linux and Windows at the same time or when your company has a policy that you must use Windows (please don't start discussing whether this is a good policy, because it isn't helping either).
    – Morty
    Jul 3, 2020 at 7:14
1

I've had exactly the same problem. Our Angular web development flow depends on file changes detected with webpack on mapped volumes.

Unfortunately, Windows does not pass file system events (that fsevents package that always warns during NPM install 😉) and instead the alternative is to enable polling, to manually check for files that have changed. This polling flag has a negative impact on CPU resources on macOS, thus it is not a great default.

There are two solutions I've found that could work. Both are based on the same conditional trick. Since Docker logic can only be configured with environment variables, we need to find an environment variable that only exists on Windows. The %WINDIR% is pretty good for that, since it even has "Windows" in the name. 😁

During Docker image build

If you need to have conditional logic for Windows during the Docker image build step, you can use build arguments. These can be specified on the CLI or with docker-compose.

For example, (partial) docker-compose.yml:

build:
  context: .
    dockerfile: dev.Dockerfile
    args:
      - WINDIR

Note, I found that the argument is case-sensitive, it has to be all caps, otherwise it isn't passed.

Then, in the Dockerfile you can add conditional shell logic in a RUN command:

ARG WINDIR
# If the host is Windows (as detected from pass-through %WINDIR% env var), set polling for file system change detection.
RUN echo 'Windows:'; if [ -n "$WINDIR" ]; then export POLL='--poll 1000'; echo 'DETECTED'; else echo 'IGNORED'; fi

It is required to specify the ARG command for this to work.
You can put any logic in between the then and/or else.

CMD execution (Docker container run)

One gotcha I encountered, was that the CMD command does not have access during docker run to environment variables set during the build. Thus that POLL env var from above cannot be accessed.

Luckily we could use shell parameter expansion to replace environment variables in the CMD command at runtime.

Example Dockerfile:

CMD npx ng serve --host 0.0.0.0 --port 4300 ${WINDIR:+--poll 1000}

The docker-compose.yml would pass-through %WINDIR% differently:

environment:
- WINDIR
0

For macOS, or any OS, you can have devs set this in their local shell profile:

export IS_HOST_MACOS='true'
export HOST_UNAME=$(uname)

Then, pass into docker via:

docker run -e IS_HOST_MACOS -i HOST_UNAME

Lastly, use it inside some docker script:

# This is meant to help developers know when the server has booted
if [ -n "${IS_HOST_MACOS+1}" ]; then
  [ "$IS_HOST_MACOS" == "true" ] && echo '{"Nginx is ready":""}';
fi
1
  • This is also good, heaven forbid one day we aren't using LINUX for servers... then I guess this piece of code won't break. May 25, 2023 at 18:33
-1

Since the container is executing in a simulated environment, you may be able to distinguish between Windows and Linux hosts by the supplied virtual hardware.

For example, from this answer I infer that Docker on Windows will create a network device called "vEthernet (DockerNAT)".

I don't have the environment for testing, so it is up to you to find a working solution for your environment(s).

0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .