I have a fairly large Windows docker image + container (it has MSVS and lots of tools, based on Windows server 2022). It runs quite slowly even on my fast 16-core Threadripper Windows 11 desktop; it seems hugely disk-bound as well as taking over 50GB of disk space (and it eats more, the longer I use it). The host machine has WSL2 and Docker Desktop (with the WSL2 back-end enabled), and Hyper-V is enabled. The container is self-contained; it doesn't bind-mount any volumes from the host.
Looking at Task Manager, the C disk is pinned at 100% active time with very slow response rates; that's never good. Using procmon I see most of the disk accesses are from "vmmem" and "docker-index", and my c:\ProgramData\Docker\windowsfilter dir fills up pretty often. And I never get more than 1 or 2 CPUs worth of compute, even though I've allocated 8 CPUs to the container (probably just because it's so disk-bound).
I've read various things about how to speed up docker containers on Windows, but since I'm not 100% clear on the underlying architecture (is dockerd running in a VM? What about docker-index? The container itself? What's the filesystem driver in the container?) I'm not sure how to go about speeding it up.
Should I remove Docker Desktop and move to "plain" Windows docker as in https://lippertmarkus.com/2021/09/04/containers-without-docker-desktop/? I don't care about the desktop GUI; I only use the CLI anyway (docker build, docker-compose up, etc.).
Should I run Docker from within WSL? Would that even work with a Windows image/container?
Should I get a clean machine and only run the docker image on it?
Any other ideas?
The fastest way is:
Install a Linux distro;
Enter Linux OS
Install Docker (https://docs.docker.com/engine/install/ubuntu/);
Make your container up with docker build or docker-compose up.
The Docker Desktop for Mac docs state
By default, Docker Desktop is set to use 2 GB runtime memory, allocated from the total available memory on your Mac. To increase the RAM, set this to a higher number. To decrease it, lower the number.
https://docs.docker.com/desktop/mac/
I am unclear what this refers to. Is it the memory available to the desktop software, to the docker virtual machine, to a running container, or to something else?
Docker Desktop for Mac runs a hidden Linux VM, and this setting controls the memory allocation for that VM. So this is the total memory available to all containers combined. Options like docker run -m can still set a per-container memory limit.
I'm attempting to increase the memory allocation of a specific container I'm running on an EC2 instance. I was able to do this locally by adding the mem_limit: 4GB into my docker-compose file (using version 2 not 3) and this did not work until I changed my settings in Docker desktop to be greater than the memory limit I was specifying:
My question is as follows, is it possible to change this memory slider setting from the command line and therefore would it be possible to do it on an EC2 instance and without docker desktop? I've been through the docs but was unable to find anything specific to this!
That's a Docker Desktop setting, which is only necessary because of the way docker containers run in a VM on Windows and Mac computers. On an EC2 Linux server there is no limit like that, docker processes can use as much resources as the server has available.
Is it possible that I run docker without any host OS. I mean run it natively. It would be a performance boost that way I believe if possible.
Suppose I have a tool which runs on linux kernel. I create a docker container with some extra dependencies. Now I share that container with other person who has linux to run that container.
But I want to run that container without host OS. as it will be double layer of OS with container.
Docker itself is not a VM, so there is no double layer of OS. Docker is a tool to run applications with settings that isolate them from other applications running on the same OS kernel. Docker does include a VM with Docker for Windows and Docker for Mac to run the Linux kernel so you can run Linux containers. There is an option to run native Windows containers with Server 2016, but if you are looking for minimal and efficiency, I would suggest looking elsewhere.
The closest things to what you are looking for are:
Unikernels: these are applications compiled into a kernel with everything else removed, designed to run inside of a VM for a very specialized task, often security related. These are still early in their development stage, but Docker does use some of their technology inside their project.
LinuxKit (part of the Moby Project): this is how Docker creates their VMs for Docker for Windows and Docker for Mac. It is a container based Linux operating system that you can custom compile with only the containers you want to run. Most of the focus of this is still designed for VMs, but bare metal is an option.
Scratch base image: if you statically compile your application to remove all of the library dependencies, you can have a container without any shell or other OS tools. This is often seen in Go binaries shipped as Docker containers to do a single task with a very small attack surface. As a Docker container, it still requires the underlying Linux OS to run the binary.
I am running a Docker daemon on my GUEST OS which is CentOS. I want to install software services on top of that in an isolated manner and I do not need another OS image inside my Docker container.
I want to have a Docker container with just the additional binaries and libraries for the software application I am going to install.
Is there a "whiteglove/blank" base image in Docker I can use ? I want a very lean container that uses as a starting point what my GUEST OS has to offer. Is that possible ?
What you're asking for isn't possible out-of-the-box with Docker. Each Docker image has its own root filesystem, which needs to have some sort of OS installed.
Your options are:
Use a minimal base image, such as the BusyBox image. This will give you the absolute minimum you need to get a container running.
Use the CentOS base image, in which case your container will be running the same or very similar OS.
The reason Docker images are like this is because they're meant to be portable. Any Docker image is meant to run anywhere Docker is running, regardless of the operating system. This means that the Docker image must contain an entire root filesystem and OS installation.
What you can do if you need stuff from the host OS is share a directory using Docker volumes. However, this is generally meant to be used for mounting data directories, and it still necessitates the Docker image having an OS.
That said, if you have a statically-linked binary that has absolutely no dependencies, it becomes easy to create a very minimal image. This is called a "microcontainer", and Go in particular is well-suited to producing these. Here is some further reading on microcontainers and how to produce them.
One other option you could look into if all you want is the resource management part of containers is using lxc-execute, as described in this answer. But you lose out on all the other nice Docker features as well. Unfortunately, what you're trying to do is just not what Docker is built for.
As I understood docker, when you use a base image, you really do not install an additional OS.
Its just a directory structure sort of thing with preinstalled programs or we can say a file system of an actual base image OS.
In most cases [click this link for the exception], docker itself [the docker engine] runs on a linux VM when used on mac and windows.
If you are confused with virtualization, there is no virtualization inside Docker Container. Containers run in user space on top of the host operating system's kernel. So, the containers and the host OS would share the same kernel.
So, to sumarize:
Consider the host OS to be windows or mac.
Docker when installed, is inside a linux VM running on these host OS.[use this resource for more info]
The base linux images inside the docker container then use this linux VM machine as host OS and not the native windows or mac.
On linux, The base linux images inside the docker container direclty uses the host OS which is linux itself without any virtualization.
The base image inside Docker Container is just the snapshot of that linux distributions programs and tool.
The base image make use of the host kernel (which in all three cases, is linux).
Hence, there is no virtualisation inside a container but docker can use a single parent linux virtual machine to run itself [the docker engine] inside it.
Conclusion:
When you install a base image inside docker, there is no additional OS that is installed inside the container but just the copy of filesystem with minimal programs and tools is created.
From Docker's best practices:
Whenever possible, use current Official Repositories as the basis for your image. We recommend the Debian image since it’s very tightly controlled and kept extremely minimal (currently under 100 mb), while still being a full distribution.
What you're asking for is completely against the idea of using Docker Containers. You don't want to have any dependability on your GUEST OS. If you do your Docker wont be portable.
When you create a container, you want it to run on any machine that runs Docker. Be it CentoOS, Ubuntu, Mac, or Microsoft Azure :)
Ideally there are no advantages of your base container OS having to do anything with your Host OS.
For any container, you need to have at least a root file system. That is why you need to use a base image that have the root file system. Your idea is not completely against the container paradigm of usage; as opposed to VMs, we want container to be minimal without much of repetitive elements that it can leverage from the underlayer OS.
Following the links of Rohan Singh, I found some related info, that doesn't generally contradict, but relates to the core ide of the question:
The base image for all Docker images is the scratch image. It has essentially nothing in it. This may sound useless, but you can actually use it to create the smallest possible image for your application, if you can compile your application to a static binary with zero dependencies like you can with Go or C.