Does Docker host network break application portability? - docker

I am containerizing a network-bound application. I want to deploy my containers with the Docker host network driver because it is the driver option that most minimizes latency.
Now let's say my container is based on ubuntu:latest and my host OS is CentOS. And let's also say my application has some network-related dependency on Ubuntu. Will my application work as expected?
What I'm ultimately driving at is whether there is any kind of isolation between host and container in terms of network when using the host driver, or do you essentially lose any portability when it comes to network dependencies?

If you specify --net host then there's no isolation between the container and the host network. On the other hand, if you're just doing straightforward TCP/UDP things, that's extremely portable across Unices and I wouldn't especially worry about host and container distributions not matching.
(If you start saying "ioctl" or "syscall" or directly use kernel headers for anything then it's worth worrying; if you depend on messing with iptables it can potentially get weird.)

Related

What is the practical use case for --net=host argument in docker?

For running a container we can specify --net=host to enable host networking, which allows the container shares the host’s networking namespace. But what is the practical use case for this?
I've found it useful in two situations:
You have a server process that listens on a very large number of ports, or does not use a consistent port, so the docker run -p option is impractical or impossible.
You have a process that needs to examine or manage the host network environment. (Its wire protocol somehow depends on sending the host's IP address; it's a service-discovery system and you want it to advertise both Docker and non-Docker services running on the host.)
Host networking disables one of Docker's important isolation systems. If you run a container with host networking, you can't use features like port remapping and you can't accept inbound connections from other containers using the container name as a host name. In both of these cases, running the server outside Docker might be more appropriate.
In SO questions I frequently see --net host suggested as a hack to get around programs that have 127.0.0.1 hard-coded as the location of a database or another external resource. This isn't usually necessary, and adding a layer of configuration (environment variables work well) and the standard Docker networking setup is better practice.

Missuse Docker Container as VM

I've read that you shouldn't ssh into a docker container. But why? I'd like to use a docker container as a replacement for a normal VM. What are the disadvantages? I know that this will create a lot of layers. But I could flatten my container on a regular base.
Can I use the container as a regular vm and what is the "worst case" that can happen?
Docker containers are optimized around running single processes. Virtual machines are optimized around running entire operating systems.
At a technical level you generally can run something that looks like a full VM inside a Docker container, but it's a lot of hand setup. For instance, a typical systemd setup wants to manage several host devices and kernel-level configuration options, and your choices to run systemd are either (a) let it manage the host and possibly conflict with the host's systemd, or (b) manually figure out which unit files you can't run and disable them. All of the prebuilt Docker images run only single services (just MySQL, just Nginx, just a Python runtime, ...) and so you're also giving up this ecosystem.
A VM certainly gives up some amount of efficiency by virtualizing hardware devices and running multiple OS kernels, but if you really want to run a VM, it's not a huge performance loss; just run a VM if that's the model you want to use.
No you can't use it as a replacement for a VM since you can only have one entrypoint on a docker container. You can not expose multiple services on multiple ports like you would on a regular virtual machine.

Apache Kafka in docker AND VirtualBox VM

I'm trying to use Apache Kafka, i.e. a version usable in connection with docker (wurstmeister/kafka-docker), in a Virtual Machine and connect to the kafka broker in the dockers over the host system of the VM.
I will describe the setup in more detail:
My host system is an Ubuntu 64 bit 14.04.3 LTS (Kernel 3.13) running on an "usual" computer. I have a complete and complex structure of various docker-containers interacting with each other. In order to not disturb, or better said, to encapsulate this whole structure, it is not an option to run the docker images directly on the host system. Another reason for that is the need for different python libraries on the host, which interfere with the python-lib version required by docker-compose (which is used to start the different docker images).
Therefore the desired solution should be to setup a virtual machine over VirtualBox (guest system: Ubuntu 16.04.1 LTS) and to completely run the docker environment in this VM. This has the distinct advantage that the VM itself can be configured exactly according to the requirements of the docker structure.
As mentioned above one of the docker images provides kafka and zookeeper functionality to use for communication and messaging. That means the .yaml file, which sets up a container running this image, forwards all necessary ports of kafka and zookeeper to the host system of the docker environment (which is the guest system of the virtual box VM). In order to also make the docker environment visible in the host system, I forwarded all the ports over network settings in VirtualBox (network -> adapter NAT -> advanced -> port forwarding). The behaviour of the system is as follows:
When I run the docker-environment (including kafka) I can connect, consume and produce from the VM-kafka, which uses the recommended standard kafka shell scripts (producer & consumer api).
When I run a Kafka and zookeeper server ON THE VM guest system, I can connect from outside the VM (host), produce and consume over producer & consumer api.
When I run Kafka in the docker environment I can connect from the host system outside the VM, meaning I can see all topics, get infos about topics, while also seeing some debug output from kafka and zookeeper in the docker.
What is not possible is unfortunately to produce or consume any message from the host system to/from the docker-kafka. From the producer API I get a "Batch expired" exception, the consumer returns with a "ClosedChannelException".
I have done a lot of googling and found a lot of hints how to solve similiar problems. Most of them refer to the advertised.host.name-parameter in kafka-server.properties, which is accessible over KAFKA_ADVERTISED_HOST_NAME in .yaml. https://stackoverflow.com/a/35374057/3770602 e.g. refers to that parameter when both the errors mentioned above occur. Unfortunately none of the scenarios feature both docker AND VM functionality.
Further more trying to modify this parameter does not have an affect at all. Although I am not very familiar with docker and kafka, I can see a problem here, as the kafka consumer and producer would get the local IP of the docker environment, which is 10.0.2.15 in the NAT case, to use as broker. But unfortunately this IP is not visibile from outside the VM. Consequently the solution would probably be a changed setup, where one should use the bridged mode in VirtualBox networking. Strange thing here is, that a bridged connection (of course) leads to an own IP of the VM over DHCP, which then leads to a non-accessible docker-kafka both from the VM AND the host system. This last behaviour seems to be very awkward to me.
Concluding my question would be, if somebody has some experiences with this or a similiar scenario and can tell me, how to configure docker-kafka, VirtualBox VM and host system. I have really tried a lot of different settings for the consumer and producer call with no success. Of course some docker, kafka or both docker & kafka experts are welcome to answer as well.
If you need additional information or you can provide some hints, please let me know.
Thanks in advance

In the perspective of runtime performance, is Docker running on cloud services efficient?

Well known cloud services provide Docker Container service. But they provide Containers running on virtual machines. They charge nothing to Docker Containers, but they charge for virtual machines which run them.
Docker Containers are faster for runtime performance compared to virtual machines, but slower than physical machines. It is known that the computation performance is almost same to physical server, but the network performance is about 70% of real machine. So the performance strength in Docker is meaningful only for running physical Container hosts. In short, a Docker Containers running on virtual machines is slower than the virtual machine itself, so it is useless to run Docker Container on cloud services as long as the cloud services provide Docker Containers in their virtual machines.
Of course, I know that it is unavoidable because Docker Containers is not as sandbox-secure as virtual machines. Then, what is the benefit of using Docker if we consider only the runtime performance?
I think that presentation is a bit old and brief in the performance section to be used as a reference for Docker performance. I can't see much setup detail on the benchmarks that were done (it might be in Korean?). Maybe try some more detailed research or recent bench marks.
http://blog.pierreroudier.net/wp-content/uploads/2015/08/rc25482.pdf
https://www.percona.com/blog/2016/08/03/testing-docker-multi-host-network-performance/
http://mysqlserverteam.com/mysql-with-docker-performance-characteristics/
Yes, there can be some network degradation in containers depending on your use case, most of which can be worked around. I certainly don't think it makes Docker containers "useless", especially when so much of a container runs at close to host speed.
One thing that I can't see any reference to in any NAT benchmarks is if they have tried disabling the Docker userland proxy --userland-proxy=false which you don't want to be using if you are trying to push the network via mapped ports (the standard way to connect to a Docker container).
Then, what is the benefit of using Docker if we consider only the
runtime performance?
Containers and Virtual Machines don't exist for run time performance. They exist so you can divide up your physical hosts into smaller and/or more easily managed partitions. If only runtime performance was considered then manufacturing custom ASIC's to run an application would be the way to go, but it very rarely is the way in the real world.
You can certainly get more out of your hardware if you run containers directly on a physical host rather than with a VM. Docker still presents enough packaging and management benefits for people to want to use it on a virtual machine, even with the small amount of additional overhead.

Easy, straightforward, robust way to make host port available to Docker container?

It is really easy to mount directories into a docker container. How can I just as easily "mount a port into" a docker container?
Example:
I have a MySQL server running on my local machine. To connect to it from a docker container I can mount the mysql.sock socket file into the container. But let's say for some reason (like intending to run a MySQL slave instance) I cannot use mysql.sock to connect and need to use TCP.
How can I accomplish this most easily?
Things to consider:
I may be running Docker natively if I'm using Linux, but I may also be running it in a VM if I'm on Mac or Windows, through Docker Machine or Docker for Mac/Windows (Beta). The answer should handle both scenarios seamlessly, without me as the user having to decide which solution is right depending on my specific Docker setup.
Simply assigning the container to the host network is often not an option, so that's unfortunately not a proper solution.
Potential solution directions:
1) I understand that setting up proper local DNS and making the Docker container (network) talk to it might be a proper, robust solution. If there is such a DNS service that can be set up with 1, max 2 commands and then "just work", that might be something.
2) Essentially what's needed here is that something will listen on a port inside the container and like a sort of proxy route traffic between the TCP/IP participants. There's been discussion on this closed Docker GH issue that shows some ip route command-line magic, but that's a bit too much of a requirement for many people, myself included. But if there was something akin to this that was fully automated while understanding Docker and, again, possible to get up and running with 1-2 commands, that'd be an acceptable solution.
I think you can run your container with --net=host option. In this case container will bind to the host's network and will be able to access all the ports on your local machine.

Resources