When I create a new docker container like with
docker run -it -m 560m --cpuset-cpus=1,2 ubuntu sleep 120
and check its namespaces, I can see that new namespaces have been created (example for pid 7047).
root#dude2:~# ls /proc/7047/ns -la
total 0
dr-x--x--x 2 root root 0 Jul 7 12:17 .
dr-xr-xr-x 9 root root 0 Jul 7 12:16 ..
lrwxrwxrwx 1 root root 0 Jul 7 12:17 ipc -> ipc:[4026532465]
lrwxrwxrwx 1 root root 0 Jul 7 12:17 mnt -> mnt:[4026532463]
lrwxrwxrwx 1 root root 0 Jul 7 12:17 net -> net:[4026532299]
lrwxrwxrwx 1 root root 0 Jul 7 12:17 pid -> pid:[4026532466]
lrwxrwxrwx 1 root root 0 Jul 7 12:17 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 Jul 7 12:17 uts -> uts:[4026532464]
root#dude2:~# ls /proc/self/ns -la
When I check with ip netns list I cannot see the new net namespace.
dude#dude2:~/docker/testroot$ ip netns list
dude#dude2:~/docker/testroot$
Any idea why?
That's because docker is not creating the reqired symlink:
# (as root)
pid=$(docker inspect -f '{{.State.Pid}}' ${container_id})
mkdir -p /var/run/netns/
ln -sfT /proc/$pid/ns/net /var/run/netns/$container_id
Then, the container's netns namespace can be examined with ip netns ${container_id}, e.g.:
# e.g. show stats about eth0 inside the container
ip netns exec "${container_id}" ip -s link show eth0
As #jary indicates, the ip netns command only works with namespace symlinks in /var/run/netns. However, if you you have the nsenter command available (part of the util-linux package), you can accomplish the same thing using the PID of your docker container.
To get the PID of a docker container, you can run:
docker inspect --format '{{.State.Pid}}' <container_name_or_Id>
To get a command inside the network namespace of a container:
nsenter -t <contanier_pid> -n <command>
E.g:
$ docker inspect --format '{{.State.Pid}}' weechat
4432
$ sudo nsenter -t 4432 -n ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
75: eth0#if76: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:1b brd ff:ff:ff:ff:ff:ff
inet 172.17.0.27/16 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::42:acff:fe11:1b/64 scope link
valid_lft forever preferred_lft forever
The above was equivalent to running ip netns exec <some_namespace> ip addr show.
As you can see here, you will need to run nsenter with root privileges.
Similar but different with #jary’s answer.
There is no need to introduce /proc/<pid>/ or netster. Only one move below to achieve what you want. Thus, you could operate containers’ network namespace just like they are created manually on host machine.
One Move:
ln -s /var/run/docker/netns /var/run/netns
Result:
Start a container:
docker run -tid ubuntu:18.04
List container:
root#Light-G:/var/run# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
972909a27ea1 ubuntu:18.04 "/bin/bash" 19 seconds ago Up 18 seconds peaceful_easley
List network namespace of this container:
root#Light-G:/var/run# ip netns list
733443afef58 (id: 0)
Delete container:
root#Light-G:/var/run# docker rm -f 972909a27ea1
972909a27ea1
List network namespace again:
root#Light-G:/var/run# ip netns list
root#Light-G:/var/run#
NOTE: THIS SEEM MUCH MORE SECURE than the symlink practice BUT MAY STILL LEAD TO SERIOUS SECURITY PROBLEMS.
It seems to me we may be violating what the containers should be - a contained environments.
That's because docker is not creating the reqired symlink:
# (as root)
pid=$(docker inspect -f '{{.State.Pid}}' "${container_id}")
mkdir -p /var/run/netns/
touch /var/run/$container_id
mount -o ro,bind "/proc/$pid/ns/net" "/var/run/netns/$container_id"
Then, the container's netns namespace can be examined with ip netns "${container_id}", e.g.:
# e.g. show stats about eth0 inside the container
ip netns exec "${container_id}" ip -s link show eth0
Thank you #TheDiveO for notifying me.
Related
I've just finished installing docker in a server with Centos, but failed to execute sudo service docker start. Executing sudo service docker restart and reboot the server doesn't help.
The report error by executing sudo dockerd:
Error creating default "bridge" network: Failed to program FILTER chain: iptables failed: iptables --wait -I FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT: iptables: No chain/target/match by that name.
(exit status 1)
It seems like docker0 cannot be found, so I have checked the iptables by ip a:
...
6: docker0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default
link/ether 02:42:81:95:ec:06 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
The docker0 exists but its state is DOWN, I don't know if it's the reason.
Some information about my docker (docker --version) and system environment (uname -a):
Docker version 19.03.4, build 9013bf583a
Linux xxxxxxxxxxxxx 4.19.91-009.ali4000.alios7.x86_64 #1 SMP Mon Jan 25 10:47:38 CST 2021 x86_64 x86_64 x86_64 GNU/Linux
Currently I don't know how to fix it.
Update
The result of executing sudo iptables -S is as follows:
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-N DOCKER
-N DOCKER-ISOLATION-STAGE-1
-N DOCKER-ISOLATION-STAGE-2
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -j RETURN
-A DOCKER-ISOLATION-STAGE-2 -j RETURN
First, I am aware of creating a VXLAN interface with tag based on ip command:
ip link add vxlan-br0 type vxlan id <tag-id> group <multicast-ip> local <host-ip> dstport 0
But it is useless for my actual demand, and my demand is to isolate multiple docker containers using different tags, something like:
brctl addif br1 veth111111 tag=10 # veth111111 is the netdev used by docker container 1
brctl addif br1 veth222222 tag=20 # veth222222 is the netdev used by docker container 2
brctl addif br1 veth333333 tag=10 # veth111111 is the netdev used by docker container 3
I want to isolate container 2 from container 1 and 3, and don't isolate communication bewteen container 1 and 3. How to achieve this?
Adding two bridge networks will provide isolation.
docker create network net1
docker create network net2
Then start some containers
docker run -d --name one --net net1 busybox sleep 600
docker run -d --name two --net net2 busybox sleep 600
docker run -d --name three --net net1 busybox sleep 600
one and three will communicate as they are attached to the same bridge
docker exec one ping three
docker exec three ping one
Others will fail as they cross networks/bridges
docker exec one ping two
docker exec two ping one
docker exec three ping two
You'll notice docker provides host/name resolution inside a network so it's actually the host name resolution that is failing above. IP's are not routed between bridges either.
$ docker exec three ip ad sh dev eth0
17: eth0#if18: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:14:00:03 brd ff:ff:ff:ff:ff:ff
inet 172.20.0.3/16 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::42:acff:fe14:3/64 scope link
valid_lft forever preferred_lft forever
Ping two
$ docker exec three ping -c 1 -w 1 172.21.0.2
PING 172.21.0.2 (172.21.0.2): 56 data bytes
--- 172.21.0.2 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss
Ping one
docker exec three ping -c 1 -w 1 172.20.0.2
PING 172.20.0.2 (172.20.0.2): 56 data bytes
64 bytes from 172.20.0.2: seq=0 ttl=64 time=0.044 ms
This setup will work with the overlay networking driver as well but that is more complex to setup.
I'm studying docker containers and now I'm trying to setup a network for docker containers.
Docker basically uses a 'docker0' bridge that has172.17.0.0/16 network and this network is not the same host network.
I want the docker container and host container to use the same network.
So now I am trying to make up docker container's network without 'bridge driver'.
I am using the 192.168.77.0/24 network by using sharer.
I want the host and docker container to use this network.
I referenced here - https://docs.docker.com/v1.7/articles/networking/#how-docker-networks-a-container.
Below are the commands that I tried to make up the network for containers.
All the commands were ran as the root user.
# ifconfig eth0 promisc
# docker run -i -t --net=none --name net_test ubuntu_net /bin/bash
# docker inspect -f '{{.State.Pid}}' net_test
# 14673
# pid=14673
# mkdir -p /var/run/netns
# ln -s /proc/$pid/ns/net /var/run/netns/$pid
# brctl addbr my_bridge
# brctl addif my_bridge eth0
# ifconfig my_bridge 192.168.77.250 up
# route del default gw 192.168.77.1
# route add default gw 192.168.77.1
# ifconfig eth0 0.0.0.0 up
# ip link add veth0 type veth peer name veth1
# brctl addif my_bridge veth0
# ip link set veth0 up
# ip link set veth1 netns $pid
# ip netns exec $pid ip link set dev veth1 name eth0
# ip netns exec $pid ip link set eth0 address 12:34:56:78:9a:bc
# ip netns exec $pid ip link set eth0 up
# ip netns exec $pid ip addr add 192.168.77.251/24 broadcast 192.168.77.255 dev eth0
# ip netns exec $pid ip route add default via 192.168.77.1
After these commands the docker container can ping to host, and the host can ping to the docker container but the container can't ping to the outside network.
Below is routing table in host after executing commands.
Destination Gateway Genmask Flags Metric Ref Use Iface
default 192.168.77.1 0.0.0.0 UG 0 0 0 my_bridge
172.17.0.0 * 255.255.0.0 U 0 0 0 docker0
192.168.77.0 * 255.255.255.0 U 0 0 0 my_bridge
Below is routing table in the docker container after executing
commands.Destination Gateway Genmask Flags Metric Ref Use Iface
default 192.168.77.1 0.0.0.0 UG 0 0 0 eth0
192.168.77.0 * 255.255.255.0 U 0 0 0 eth0
but the docker container can't ping to gateway(192.168.77.1) too.
I'm using ubuntu 14.04 LTS desktop verison.
and I didn't set any firewalls.
Am I setting anything wrong? Thanks.
I've been looking into LXC containers and I was wondering as to whether or not it is possible to use an LXC container like an ordinary VPS?
What I mean is;
How do I assign an external IP address to an LXC container?
How do I ssh into an LXC container directly?
I'm quite new to LXC containers so please let me know if there are any other differences I should be aware of.
lxc-create -t download -n cn_name
lxc-start -n cn_name -d
lxc-attach -n cn_name
then in container cn_name install openssh server so you can use ssh then reboot it or restart ssh service.
To make any container "services" available to the world configure port forwarding from the host to the container.
For instance if you had a web server in a container, to forward port 80 from the host ip 192.168.1.1 to a container with ip 10.0.3.1 you can use the iptables rule below.
iptables -t nat -I PREROUTING -i eth0 -p TCP -d 191.168.1.1/32 --dport 80 -j DNAT --to-destination 10.0.3.1:80
now the web server on port 80 of the container will be available via port 80 of the host OS.
It sounds like what you want is to bridge the host NIC to the container. In that case, the first thing you need to do is create a bridge. Do this by first ensuring bridge-utils is installed on the system, then open /etc/networking/interfaces for editing and change this:
auto eth0
iface eth0 inet dhcp
to this:
auto br0
iface br0 inet dhcp
bridge-interfaces eth0
bridge-ports eth0
up ifconfig eth0 up
iface eth0 inet manual
If your NIC is not named eth0, you should replace eth0 with whatever your NIC is named (mine is named enp5s0). Once you've made the change, you can start the bridge by issuing the command
sudo ifup br0
Assuming all went well, you should maintain internet access and even your ssh session should stay online during the process. I recommend you have physical access to the host because messing up the above steps could block the host from internet access. You can verify your setup is correct by running ifconfig and checking that br0 has an assigned IP address while eth0 does not.
Once that's all set up, open up /etc/lxc/default.conf and change
lxc.network.link = lxcbr0
to
lxc.network.link = br0
And that's it. Any containers that you launch will automatically bridge to eth0 and will effectively exist on the same LAN as the host. At this point, you can install ssh if it's not already and ssh into the container using its newly assigned IP address.
"Converting eth0 to br0 and getting all your LXC or LXD onto your LAN"
i have managed to cross compile ntpd 4.2.6p5 for my arm box. I have a custom toolchain provided by the manufacturer.
Box is running busybox + some variant of debian linux.
So I have no installation of ntp and did a manual copy, created a conf file for the ntpd and tried to run it.
ntpd always returns this when in debug mode:
~/ntp # ./ntpd -c ntp.conf -d
ntpd 4.2.6p5#1.2349 Mon Apr 7 19:58:25 UTC 2014 (1)
9 Apr 07:39:44 ntpd[3592]: signal_no_reset: signal 13 had flags 4000000
9 Apr 07:39:44 ntpd[3592]: proto: precision = 91.000 usec event at 0 0.0.0.0 c01d 0d
kern kernel time sync enabled
Finished Parsing!!
9 Apr 07:39:44 ntpd[3592]: ntp_io: estimated max descriptors: 1024, initial socket
boundary: 16
9 Apr 07:39:44 ntpd[3592]: Listen and drop on 0 v4wildcard 0.0.0.0 UDP 123
9 Apr 07:39:44 ntpd[3592]: unable to bind to wildcard address :: - another process
may be running - EXITING
before that I had to add into /etc/services also
ntp 123/udp
my ntp.conf looks like:
~/ntp # cat ntp.conf
server 193.2.4.6
server 193.2.4.2
driftfile ntp.drift
So I have checked netstat and nothing is running on port 123, no ntpdate etc...
~/ntp # netstat -rn
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
0.0.0.0 192.168.3.1 0.0.0.0 UG 0 0 0 eth0
192.168.3.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
~ # netstat -a | grep 123
~ #
Therefore it must be something with the config, or this arm box does not have something configured...
Oh and running manually ntpdate works:
~/ntp # ./ntpdate 193.2.4.6
9 Apr 07:49:16 ntpdate[3614]: step time server 193.2.4.6 offset -0.755704 sec
~/ntp #
So yes i could use ntpdate in cron, but this is not my intent!
Any idea?
Thank you and best regards!
The following error indicates that ntp had trouble binding to the ipv6 wildcard:
9 Apr 07:39:44 ntpd[3592]: unable to bind to wildcard address :: - another process
may be running - EXITING
I think your problem is ipv6 but it is hard to tell because your diagnosticinformation was not very good. Your netstat -a |grep 123 command is useless because netstat would substitute ntp for port 123. Try it again with:
netstat -a -n | grep 123
Along those lines netstat -rn only works with ipv4, try it again with -6:
netstat -r -n -6
Your test ntpdate used an ipv4 host. Does your server support ipv6? What happens when you run:
$ sntp -d -6 time.nist.gov
I used sntp because I do not know if ntpdate has a -6option and sntp does.