Internal infrastructure with docker - security

I have a small company network with the following services/servers:
Jenkins
Stash (Atlassian)
Confluence (Atlassian)
LDAP
Owncloud
zabbix (monitoring)
puppet
and some Java web apps
all running in separate kvm(libvirt)-vms in separate virtual-subnets on 2 machines (1 internal, 1 hetzner-rootserver) with shorewall inbetween. I'm thinking about switching to Docker.
But I have two questions:
How can I achieve network security between docker containers (i.e. I want to prevent owncloud to access any host in the network except ldap-hosts-sslport)
Just by using docker-linking? If yes: does docker really allow to access only linked containers, but no others?
By using kubernetes?
By adding multiple bridging-network-interfaces for each container?
Would you switch all my infra-services/-servers to docker, or a hybrid solution with just the owncloud and the java-web-apps on docker?

Regarding the multi-host networking: you're right that Docker links won't work across hosts. With Docker 1.9+ you can use "Docker Networking" like described in their blog post http://blog.docker.com/2015/11/docker-multi-host-networking-ga/
They don't explain how to secure the connections, though. I strongly suggest to enable TLS on your Docker daemons, which should also secure your multi-host network (that's an assumption, I haven't tried).
With Kubernetes you're going to add another layer of abstraction, so that you'll need to learn working with the pods and services concept. That's fine, but might be a bit too much. Keep in mind that you can still decide to use Kubernetes (or alternatives) later, so the first step should be to learn how you can wrap your services in Docker containers.
You won't necessarily have to switch everything to Docker. You should start with Jenkins, the Java apps, or OwnCloud and then get a bit more used to the Docker universe. Jenkins and OwnCloud will give you enough challenges to gain some experience in maintaining containers. Then you can evaluate much better if Docker makes sense in your setup and with your needs to be applied to the other services.
I personally tend to wrap everything in Docker, but only due to one reason: keeping the host clean. If you get to the point where everything runs in Docker you'll have much more freedom to choose where a service can run and you can move containers to other hosts much more easily.
You should also explore the Docker Hub, where you can find ready to run solutions, e.g. Atlassian Stash: https://hub.docker.com/r/atlassian/stash/
If you need inspiration for special applications and how to wrap them in Docker, I recommend to have a look in https://github.com/jfrazelle/dockerfiles - you'll find a bunch of good examples there.

You can give containers their own IP from your subnet by creating a network like so:
docker network create \
--driver=bridge \
--subnet=135.181.x.y/28 \
--gateway=135.181.x.y+1 \
network
Your gateway is the IP of your subnet + 1 so if my subnet was 123.123.123.123 then my gateway should be 123.123.123.124
Unfortunately I have not yet figured out how to make the containers appear to the public from their own ip, at the moment they appear as the dedicated servers' ip. Let me know if you know how I can fix that. I am able to access the container using its ip though.

Related

Is it valid to share unix socket files across (docker) containers in general?

I'm having the issue (which seems to be common) that I'm dockerizing applications that run on one machine, and these applications, now, need to run in different containers (because that's the docker paradigm and how things should be done). Currently I'm having issues with postfix and dovecot... people have found this too painful that there are tons of containers running both dovecot and postfix in one container, and I'm doing my best to do this right, but the lack of inet protocol examples (over tcp) is just too painful to continue with this. Leave alone bad logging and things that just don't work. I digress.
The question
Is it correct to have shared docker volumes that have socket files shared across different containers, and expect them to communicate correctly? Are there limitations that I have to be aware of?
Bonus: Out of curiosity, can this be extended to virtual machines?
EDIT: I would really appreciate sharing the source of the information you provide.
A Unix socket can't cross VM or physical-host boundaries. If you're thinking about ever deploying this setup in a multi-host setup like Kubernetes, Docker Swarm, or even just having containers running on multiple hosts, you'll need to use some TCP-based setup instead. (Sharing files in these environments is tricky; sharing a Unix socket actually won't work.)
If you're using Docker Desktop, also remember that runs a hidden Linux virtual machine, even on native Linux. That may limit your options. There are other setups that more directly use a VM; my day-to-day Docker turns out to be Minikube, for example, which runs a single-node Kubernetes cluster with a Docker daemon in a VM.
I'd expect sharing a Unix socket to work only if the two containers are on the same physical system, and inside the same VM if appropriate, and with the same storage mounted into both (not necessarily in the same place). I'd expect putting the socket on a named Docker volume mounted into both containers to work. I'd probably expect a bind-mounted host directory to work only on a native Linux system not running Docker Desktop.

Best Practise for docker intercontainer communication

I have two docker containers A and B. On container A a django application is running. On container B a WEBDAV Source is mounted.
Now I want to check from container A if a folder exists in container B (in the WebDAV mount destination).
What is the best solution to do something like that? Currently I solved it mounting the docker socket into the container A to execute cmds from A inside B. I am aware that mounting the docker socket into a container is a security risk for the host and the whole application stack.
Other possible solutions would be to use SSH or share and mount the directory which should be checked. Of course there are further possible solutions like doing it with HTTP requests.
Because there are so many ways to solve a problem like that, I want to know if there is a best practise (considering security, effort to implement, performance) to execute commands from container A in contianer B.
Thanks in advance
WebDAV provides a file-system-like interface on top of HTTP. I'd just directly use this. This requires almost no setup other than providing the other container's name in configuration (and if you're using plain docker run putting both containers on the same network), and it's the same setup in basically all container environments (including Docker Swarm, Kubernetes, Nomad, AWS ECS, ...) and a non-Docker development environment.
Of the other options you suggest:
Sharing a filesystem is possible. It leads to potential permission problems which can be tricky to iron out. There are potential security issues if the client container isn't supposed to be able to write the files. It may not work well in clustered environments like Kubernetes.
ssh is very hard to set up securely in a Docker environment. You don't want to hard-code a plain-text password that can be easily recovered from docker history; a best-practice setup would require generating host and user keys outside of Docker and bind-mounting them into both containers (I've never seen a setup like this in an SO question). This also brings the complexity of running multiple processes inside a container.
Mounting the Docker socket is complicated, non-portable across environments, and a massive security risk (you can very easily use the Docker socket to root the entire host). You'd need to rewrite that code for each different container environment you might run in. This should be a last resort; I'd consider it only if creating and destroying containers would need to be a key part of this one container's operation.
Is there a best practise to execute commands from container A in contianer B?
"Don't." Rearchitect your application to have some other way to communicate between the two containers, often over HTTP or using a message queue like RabbitMQ.
One solution would be to mount one filesystem readonly on one container and read-write on the other container.
See this answer: Docker, mount volumes as readonly

Docker containers as virtual desktop clones

I see that a number of people have set up Docker containers with Guacamole or other tools to allow them to remote in to GUI as if the container was a remote Linux desktop. A friend of mine had a conversation with a professor who told him that they set up Ubuntu desktop access for their students via ubuntu/rdp docker containers.
It's an attractive concept for efficiently packed cloned desktops since you don't need 50 copies of the guest OS, but how would you manage such a swarm without a connection broker like a VDI solution or a hypervizer console like a KVM setup? Would you simply use standard docker (or swarm) management tools to manage the containers themselves, then some separate remote client for the actual remote control connections?
I'm currently reading up on Docker, but unclear: If each desktop is the same, so say Firefox, LibreOffice, etc. Is there any way to gain efficiency by sharing these resources as well? For instance, could there be a container with those resources that the others all connect to... or have it shared on a lower level like the OS? Looking for any way to gain efficiency, lower overall cpu, ram, etc for all combined machines on server. Really looking for anything other than a separate copy of the same thing in each container.
I see that there are solutions for shared persistent storage in containers like Hatchway. Are there other issues caused by statelessness of the container that this does not address?
Also, I see a few ways people have cobbled together internet connectivity for docker containers (like IP per container), but most of the older posts are people frustrated with the process. Is there now a standard or preferred way to do something like this?
Or, if docker/containers are absolutely the wrong way to go about setting up the most efficient possible Linux remote desktop clones, I'd love to understand exactly what part does not work so I can find the right way.
I see after days of reading that LXD is actually what I'm looking for (Linux machine containers) instead of Docker (process containers).

Making multiple Docker Machines accessible across local network. Linux & Mac

I know there are several questions similar to this, but as far as I can see there's not an answer for the setup that I can get to work, and as far as documentation goes I'm a bit lost.
My goal is to set up a linux development server on the local network which I can run multiple docker machines / containers on for each of our projects.
Ideally, I would create a docker-machine on the dev box, and then be able to access that from any of my local network machines. I can run docker on the linux box directly and access by publishing the ports, but I want to run multiple machines with different ip addresses so that we can have multiple VMs running (multiple projects).
I've looked at Docker Swarm and overlay networks and just not been able to find a single tutorial or set of instructions to get this sort of set up running.
So I have a dev box at 192.168.0.101 with docker-machine on. I want to create a new machine, run nginx on it, and then access nginx from another machine on the local network i..e http://192.168.99.1/ then set up another and access that too at say http://192.168.99.2/.
If anyone has managed to do this i'd be interested to know how.
One way I've been thinking about doing it, is running nginx on the local host on the dev box, and set up config rules to proxy to the local machines, unsure how well this would work (it works for web servers, but what if I want to ssh or bash into one of those machines, or if one has a mysql container I want to connect to)
Have you considered running your docker machines inside LXD containers?
Stepane Grabers site has a lot of relevant information
https://stgraber.org/category/lxd/
The way that I resolved this, is by using a NAT on the linux box, and then assigning a different ip to each machine. I followed the instructions here; http://blog.oddbit.com/2014/08/11/four-ways-to-connect-a-docker/ which finally got me to be able to share multiple docker machines using the same ports (80), on different ips.

Docker : Linking containers on different host machines

How can i connect two containers on different host machines in Docker ? I need to use data from mongodb on one host by a nodejs application on another host ? Can any one give me an example like this?
You could use the abassador pattern for container linking
http://docs.docker.com/articles/ambassador_pattern_linking/
Flocker is also addressing this issue, but needs more time for infrastructure setup:
https://docs.clusterhq.com/en/0.3.2/gettingstarted/
You might want to checkout also Kontena (http://www.kontena.io). Kontena supports multicast (provided by Weave) and DNS service discovery. Because of DNS discovery you can predict before the deploy what addresses each container will get.
As Flocker, Kontena also needs some time for infrastructure setup: https://github.com/kontena/kontena/tree/master/docs#getting-started
But you will get service scaling and deploy automation as a bonus.
You can connect container from different host by creating an overlay network.
Docker Engine supports multi-host networking out-of-the-box through
the overlay network driver.
It doesn't matter what machine the other container is on, all you need to is ensure that the port is exposed on that machine and then direct the second container on the first machine to the IP of the second machine.
Machine 1: Postgres:5432 172.25.8.10 ifconfig
Machine 2: Web Server:80 172.25.8.11 -> Point DB to 172.25.8.10:5432

Resources