New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Links and Container Naming #2162

Merged
merged 42 commits into from Oct 29, 2013

Conversation

Projects
None yet
9 participants
@crosbymichael
Contributor

crosbymichael commented Oct 10, 2013

Links - Spec

Links are a way of expressing a relationship between one container and another. When you link a container, you create a parent/child relationship between the two. As a side effect links also allow you to name containers and reference them by name. Containers can be references by more than one name.

Breaking changes

This the new link feature we will be disabling intercontainer communication by default. Containers will not be able to communicate with each other over the docker0 bridge without having a link to that container. Even with a link, a parent can only communicate to the ports exposed by the child and nothing more.

Initially links will be expressed by injecting the child's data into the parent's environment accessible via namespaced variables:

Examples

  • REDIS_ENV_{key}={value}
  • REDIS_PORT={value}
  • REDIS_PORT_6379_TCP={value}.

Create a named container

docker run -d -name db1 crosbymichael/redis
32da9f6caf76

docker ps
ID              IMAGE                  CMD                     EXPOSES      NAMES
32da9f6caf76    crosbymichael/redis    /redis/src/redis-ser    6379/tcp     db1

Link a container into another

Using the container named 'db1' from our previous example we will create a relationship between our webapp container and redis.

To create a link between two containers you add the -link flag to your docker run command passing the name and alias of the container that you want to link as the child. The alias will be used as the namespace to set environment variables in the parent container. The format is -link <name>:<alias>. The alias will be converted to ALL_CAPS when environment variables are created.

# run a new webapp container and add our redis database as a child
docker run -name frontend -link db1:redis -t -i webapp sh


# access the environment inside our webapp conatiner to collect to redis

BusyBox v1.19.3 (Ubuntu 1:1.19.3-7ubuntu1.1) built-in shell (ash)
Enter 'help' for a list of built-in commands.

/ #

echo $REDIS_PORT_6379_ADDR
tcp://172.17.0.2:6379
./redis-cli -h 172.17.0.2
redis 172.17.0.2:6379>

# back on the host

docker ps
ID              IMAGE                 CMD                     EXPOSES        NAMES
32da9f6caf76    crosbymichael/redis   /redis/src/redis-ser    6379/tcp       db1, frontend/redis
37ewg328232g    webapp                sh                                     frontend

# List all the links 

# we can see that our redis container is now a child of our webapp

Remove redis as a child of frontend

docker rm -link frontend/redis

Introspecting the linked container's environment

Lets run another redis container with a password that the client must use to connect. We store the password in the environment of the container so we can use introspection to retreive the password by the parent.

REDIS=$(docker run -d -e PASSWORD=dockerpass crosbymichael/redis --requirepass dockerpass)

docker link $REDIS db1

docker run -t -i -link db1:redis webapp sh

# inside the webapp container

BusyBox v1.19.3 (Ubuntu 1:1.19.3-7ubuntu1.1) built-in shell (ash)
Enter 'help' for a list of built-in commands.

echo $db_PORT_6379_ADDR
tcp://172.17.0.2:6379
./redis-cli -h 172.17.0.2 -a $db_ENV_PASSWORD
redis 172.17.0.2:6379> set hello world
OK
redis 172.17.0.2:6379>

Client Libs

With client libs you can simplify links more.

import docker
import time
from redis import Redis

proto, ip, port = docker.require('redis')
password = docker.require_env('redis', 'password')

r = Redis(host=ip, port=int(port), password=password)

print 'Connected to redis...'

r.set('name', 'docker')
while True:
        print r.get('name')
        time.sleep(1)

TLDR

Links are a way to express relationships between containers and allow introspection based on those relationships.

Show outdated Hide outdated commands.go
Show outdated Hide outdated runtime.go
@mattapperson

This comment has been minimized.

Show comment
Hide comment
@mattapperson

mattapperson Oct 20, 2013

Contributor

Love this idea!

Contributor

mattapperson commented Oct 20, 2013

Love this idea!

@paulepanter

This comment has been minimized.

Show comment
Hide comment
@paulepanter

paulepanter Oct 24, 2013

Reading the proposal, I do not fully understand this. Why are names and links related at all? Why can’t the host name, passed with -h to docker run, simply be used as the name for a container?

I also do not understand, why the relationship has to be parent and child? Why the different levels?

paulepanter commented Oct 24, 2013

Reading the proposal, I do not fully understand this. Why are names and links related at all? Why can’t the host name, passed with -h to docker run, simply be used as the name for a container?

I also do not understand, why the relationship has to be parent and child? Why the different levels?

@vieux

View changes

Show outdated Hide outdated runtime.go
@tianon

This comment has been minimized.

Show comment
Hide comment
@tianon

tianon Oct 25, 2013

Member

The pseudo-docs here appear to be somewhat out of date. The first example mentions REDIS_PORT_6379_ADDR, but all I get is REDIS_PORT_6379_TCP (and REDIS_PORT and REDIS_NAME).

Also, the later example has db_PORT_6379_ADDR, but the env vars are always all-uppercased, aren't they? I realize these are semi-unofficial, but official docs will probably at least be based in part on them, and us mere mortals are learning the links feature from them in the meantime. :)

Member

tianon commented Oct 25, 2013

The pseudo-docs here appear to be somewhat out of date. The first example mentions REDIS_PORT_6379_ADDR, but all I get is REDIS_PORT_6379_TCP (and REDIS_PORT and REDIS_NAME).

Also, the later example has db_PORT_6379_ADDR, but the env vars are always all-uppercased, aren't they? I realize these are semi-unofficial, but official docs will probably at least be based in part on them, and us mere mortals are learning the links feature from them in the meantime. :)

@tianon

This comment has been minimized.

Show comment
Hide comment
@tianon

tianon Oct 25, 2013

Member

Oh, reading back up, I see you initially describe the correct vars, they're just not necessarily correct in the examples. 👍

Member

tianon commented Oct 25, 2013

Oh, reading back up, I see you initially describe the correct vars, they're just not necessarily correct in the examples. 👍

alexlarsson and others added some commits Sep 17, 2013

Use netlink directly instead of /bin/ip in Sysinit
The sysinit code only uses /bin/ip to set a default gateway. This
is pretty easy to do via netlink directly, so we can avoid
the ip dependency.
Add a network test
This just tries pinging first 127.0.0.1 and then 8.8.8.8.

We can't ping via a dns name, because libresolv.so is missing
from the test image, so dns resolving doesn't work.
network: Stop shelling out to /sbin/ip
We have our own netlink version of all the required calls now, so
we can just skip the /sbin/ip dependency.
Add netlink submodule
This contains various operations that can replace the use of
shelling out to "ip".
Move ListOps to utils submodule
This will be needed for later use in docker-init without a docker
dependency
Move SysInit to a submodule
This allows docker-init to not import the main docker
module, which means it won't e.g. pick up any sqlite
dependencies.
Updated fixes post rebase from master
Removed test cases that are no longer
applicable with links and the port changes.
Remove test case where a test was hitting an
external ip.
Add dynbinary and dyntest scripts for building/testing a separate sta…
…tic dockerinit binary

After a nice long brainstorming session with @shykes on IRC, we decided on using a SHA1 hash of dockerinit compiled into the dynamic docker binary to ensure that we always use the two in a perfect pair, and never mix and match.
@shykes

This comment has been minimized.

Show comment
Hide comment
@shykes

shykes Oct 26, 2013

Collaborator

Guys (@crosbymichael and @vieux) is this ready for review and merge? This branch is growing way too large, I'm seeing all sorts of things unrelated to links in there.

Collaborator

shykes commented Oct 26, 2013

Guys (@crosbymichael and @vieux) is this ready for review and merge? This branch is growing way too large, I'm seeing all sorts of things unrelated to links in there.

@crosbymichael

This comment has been minimized.

Show comment
Hide comment
@crosbymichael

crosbymichael Oct 26, 2013

Contributor

@shykes

Yes this is ready for a final review and merge. The only thing that is not releated to links in this branch is the static dockerinit changes, nothing else.

Contributor

crosbymichael commented Oct 26, 2013

@shykes

Yes this is ready for a final review and merge. The only thing that is not releated to links in this branch is the static dockerinit changes, nothing else.

vieux and others added some commits Oct 28, 2013

Merge pull request #2422 from dotcloud/links_names_generator
Add name generator for container without -name
Add -name for docker run
Remove docker link
Do not add container id as default name
Create an auto generated container name if not
specified at runtime.
@shykes

This comment has been minimized.

Show comment
Hide comment
@shykes

shykes Oct 29, 2013

Collaborator

LGTM

image

Collaborator

shykes commented Oct 29, 2013

LGTM

image

@shykes

This comment has been minimized.

Show comment
Hide comment
@shykes

shykes Oct 29, 2013

Collaborator

Note: the spec in this issue is now out-of-date. But as long as the docs are not, it doesn't matter :)

Collaborator

shykes commented Oct 29, 2013

Note: the spec in this issue is now out-of-date. But as long as the docs are not, it doesn't matter :)

crosbymichael added a commit that referenced this pull request Oct 29, 2013

Merge pull request #2162 from dotcloud/links
Links and Container Naming

@crosbymichael crosbymichael merged commit b038b0c into master Oct 29, 2013

@shykes

This comment has been minimized.

Show comment
Hide comment
@shykes

shykes Oct 29, 2013

Collaborator

NOTE @crosbymichael: I updated the text of the pull request to match the latest version :)

Collaborator

shykes commented Oct 29, 2013

NOTE @crosbymichael: I updated the text of the pull request to match the latest version :)

@tobstarr

This comment has been minimized.

Show comment
Hide comment
@tobstarr

tobstarr Nov 14, 2013

Contributor

Is that really necessary in the base package? This breaks cross compilation of the docker root package when being used as a library.

Contributor

tobstarr commented on runtime.go in 7c08aee Nov 14, 2013

Is that really necessary in the base package? This breaks cross compilation of the docker root package when being used as a library.

This comment has been minimized.

Show comment
Hide comment
@fsouza

fsouza Nov 14, 2013

Contributor

Yes, it is. This import registers the sqlite3 driver, see line 606.

Contributor

fsouza replied Nov 14, 2013

Yes, it is. This import registers the sqlite3 driver, see line 606.

@crosbymichael crosbymichael deleted the links branch Jan 17, 2014

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment