https://docs.oracle.com/cd/E52668_01/E54669/html/section_rsr_p2z_fp.html
26.9 Communicating Between Docker Containers
You can use the --link option with docker run to make network connection information about a server container available to a client container. The client container uses a private networking interface to access the exposed port in the server container. Docker sets environment variables about the server container in the client container that describe the interface and the ports that are available.
The following example demonstrates how to link an
oraclelinux:6.6
-based client container with an HTTP server container based on the mymod/httpd:v2
image that you created in Section 26.8, “Creating a Docker Image from a Dockerfile”.
To create an HTTP server and client containers that are linked:
- Create an HTTP server container named
http_server
:[root@host ~]#
docker run -d --name http_server mymod/httpd:v2
a47169154222329eed66762128755cd9fdd24d0f27ff8e0f678ef136bbc66d03 - Create a client container named
client1
that runs the bash shell and is linked to thehttp_server
container:[root@host httpd]#
docker run --rm -t -i --name client1 --link http_server:server
\oraclelinux:6.6 /bin/bash
[root@client1 ~]#The argument http_server:server to the --link option aliases the namehttp_server
asserver
. Docker converts the alias to upper case (SERVER
) and uses this string when setting up the names of the environment variables on the client.
You can now view the environment variables in the
client1
container. You can also use ping to detect the server container by name or IP address, and use curl to access the web server running on the server:[root@client1 ~]#env
HOSTNAME=10815c22e5b4 TERM=xterm SERVER_PORT=tcp://172.17.0.16:80 PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin PWD=/ SERVER_PORT_80_TCP_PORT=80 SERVER_PORT_80_TCP_ADDR=172.17.0.16 SERVER_PORT_80_TCP=tcp://172.17.0.16:80 SERVER_PORT_80_TCP_PROTO=tcp SHLVL=1 SERVER_NAME=/client1/server HOME=/ _=/usr/bin/env [root@client1 ~]#ping -c 1 server
PING server (172.17.0.16) 56(84) bytes of data. 64 bytes from server (172.17.0.16): icmp_seq=1 ttl=64 time=0.105 ms --- server ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 0.105/0.105/0.105/0.000 ms [root@client1 ~]#ping -c 1 172.17.0.16
PING 172.17.0.16 (172.17.0.16) 56(84) bytes of data. 64 bytes from 172.17.0.16: icmp_seq=1 ttl=64 time=0.171 ms --- 172.17.0.16 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 0.171/0.171/0.171/0.000 ms [root@client1 ~]#curl http://server
HTTP server running on guest [root@client1 ~]#curl http://172.17.0.16
HTTP server running on guest
You can start multiple client container instances with different names, each of which can access port 80 on the server container. Docker assigns a different IP address to each client. As shown in the following example output, Docker creates an entry for the server in the
/etc/hosts
files on each client but it does not create entries for the names of the client containers themselves:[root@client1 ~]#cat /etc/hosts
172.17.0.17 10815c22e5b4 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters 172.17.0.16 server [root@client1 ~]#ping -c 1 client2
ping: unknown host client2 [root@client1 ~]#ping -c 1 172.17.0.18
PING 172.17.0.18 (172.17.0.18) 56(84) bytes of data. 64 bytes from 172.17.0.18: icmp_seq=1 ttl=64 time=0.268 ms --- 172.17.0.18 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 0.268/0.268/0.268/0.000 ms
By default, the clients are visible to each other on the private network only by their IP addresses.
The docker ps command shows the containers that are running:
[root@host ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
449abeac3041 oraclelinux:6.6 /bin/bash ... Up 1 minutes client2
10815c22e5b4 oraclelinux:6.6 /bin/bash ... Up 2 minutes client1
a47169154222 mymod/httpd:v2 /usr/sbin/httpd ... Up 3 minutes 80/tcp
client1/server,client2/server,http_server
The
NAMES
column shows that http_server
is linked to client1
and client2
as server
. The PORTS
column shows that Docker has not remapped TCP port 80 on http_server
to another port on the host.
Note
This simple example demonstrates how to link containers. You should not use it as the basis of a production application.
The following example demonstrates how to link a container that is running a MySQL server with a container running an HTTP server.
First of all, we define a Dockerfile for the MySQL server, which we place in the
/var/docker_projects/mymod/mysql
directory:FROM oraclelinux:6.6 ENV http_proxy http://proxy.mydom.com:80 RUN yum install -y mysql-server ADD my.cnf /etc/my.cnf ADD run.sh /opt/run.sh RUN chmod 744 /opt/run.sh ENTRYPOINT /opt/run.sh
The instruction keywords define how to create the image:
ADD
- Copy the files
my.cnf
andrun.sh
from the/var/docker_projects/mymod/mysql
directory to/etc/my.cnf
and/opt/run.sh
in the container. ENTRYPOINT
- Specify that the container always runs
/opt/run.sh
. ENV
- Define the web proxy in the build environment (as an alternative to modifying
/etc/yum.conf
). FROM
- Define
oraclelinux:6.6
as a basis for the new image. RUN
- Install the
mysql-server
package and make the/opt/run.sh
script executable.
The
my.cnf
file in /var/docker_projects/mymod/mysql
contains the database configuration:[mysqld] bind-address=0.0.0.0 console=1 general_log=1 general_log_file=/dev/stdout log_error=/dev/stderr collation-server=utf8_unicode_ci character-set-server=utf8 datadir=/var/lib/mysql
The
run.sh
file in /var/docker_projects/mymod/mysql
contains the shell script for starting the database:#!/bin/bash chown -R mysql:mysql /var/lib/mysql mysql_install_db --user=mysql > /dev/null /usr/libexec/mysqld --user mysql --bootstrap << SQL FLUSH PRIVILEGES; GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION; CREATE USER dbuser IDENTIFIED BY 'secret'; CREATE DATABASE MYDB; USE MYDB; GRANT ALL ON MYDB.* to 'dbuser'@'%'; SQL /usr/bin/mysqld_safe --user mysql
Having set up the Dockerfile and the files
my.cnf
and run.sh
, we can now build the image mymod/mysql:v1
and create an instance of this container named db
that uses the standard MySQL connection port (3306):#docker build -t="mymod/mysql:v1" /var/docker_projects/mymod/mysql
Uploading context 5.12 kB Uploading context Step 0 : FROM oraclelinux:6.6 ---> d56e767abb61 Step 1 : ENV http_proxy http://proxy.mydom.com:80 ---> Running in 2d6ad386263d ---> f92df8c449eb ... Step 6 : ENTRYPOINT /opt/run.sh ---> Running in 61e7e5bab9a1 ---> 54b6e9473375 Removing intermediate container 61e7e5bab9a1 Successfully built 54b6e9473375 #docker run -d --name db -p 3306:3306 mymod/mysql:v1
ba8816c540513a892aa89828b5cf33464a7bb4616b56177266033d3311d0e00d
We next define a Dockerfile for the HTTP server, which we place in the
/var/docker_projects/mymod/httpd2
directory:FROM oraclelinux:6.6 ENV http_proxy http://proxy.mydom.com:80 RUN yum install -y httpd perl perl-DBI.x86_64 libdbi-dbd-mysql.x86_64 perl-DBD-MySQL.x86_64 ADD version.pl /var/www/cgi-bin/version.pl RUN chmod 755 /var/www/cgi-bin/version.pl ADD initdb.pl /var/www/cgi-bin/initdb.pl RUN chmod 755 /var/www/cgi-bin/initdb.pl ADD doquery.pl /var/www/cgi-bin/doquery.pl RUN chmod 755 /var/www/cgi-bin/doquery.pl RUN sed -i -e '/<Directory "\/var\/www\/cgi-bin">/,/<\/Directory>/c\\\ <Directory "/var/www/cgi-bin">\n\ Options +ExecCGI\n\ AddHandler cgi-script .pl .cgi\n\ </Directory>' /etc/httpd/conf/httpd.conf EXPOSE 80 ENTRYPOINT /usr/sbin/httpd -D FOREGROUND
This Dockerfile modifies the container's HTTP server configuration file (
/etc/httpd/conf/httpd.conf
) to allow the use of CGI scripts and installs the following Perl scripts from the /var/docker_projects/mymod/httpd2
directory:version.pl
- Connecst to the database and returns its version.
#!/usr/bin/perl use DBI; print "Content-type: text/html\n\n"; my $dbh = DBI->connect( "dbi:mysql:dbname=MYDB:host=db", "dbuser", "secret", { RaiseError => 1 }, ) or die $DBI::errstr; my $sth = $dbh->prepare("SELECT VERSION()"); $sth->execute(); my $ver = $sth->fetch(); print "Version = ", @$ver, "\n"; $sth->finish(); $dbh->disconnect();
initdb.pl
- Sets up the database and populates a table with several entries.
#!/usr/bin/perl use strict; use DBI; print "Content-type: text/html\n\n"; my $dbh = DBI->connect( "dbi:mysql:dbname=MYDB:host=db", "dbuser", "secret", { RaiseError => 1} ) or die $DBI::errstr; $dbh->do("DROP TABLE IF EXISTS PEOPLE"); $dbh->do("CREATE TABLE People(Id INT PRIMARY KEY, Name TEXT, Age INT) ENGINE=InnoDB"); $dbh->do("INSERT INTO People VALUES(1,'Alice',42)"); $dbh->do("INSERT INTO People VALUES(2,'Bobby',27)"); $dbh->do("INSERT INTO People VALUES(3,'Carol',29)"); $dbh->do("INSERT INTO People VALUES(4,'Daisy',20)"); $dbh->do("INSERT INTO People VALUES(5,'Eddie',35)"); $dbh->do("INSERT INTO People VALUES(6,'Frank',21)"); my @noerr = ('Rows inserted in People table'); print @noerr; print "\n"; my $sth = $dbh->prepare( "SELECT * FROM People" ); $sth->execute(); for ( 1 .. $sth->rows() ) { my ($id, $name, $age) = $sth->fetchrow(); print "$id $name $age\n"; } $sth->finish(); $dbh->disconnect();
doquery.pl
- Performs a simple query on the database, using the command argument as data for the query.
#!/usr/bin/perl use strict; use DBI; print "Content-type: text/html\n\n"; my $dbh = DBI->connect( "dbi:mysql:dbname=MYDB;host=db", "dbuser", "secret", { RaiseError => 1 }, ) or die $DBI::errstr; my $sth = $dbh->prepare( "SELECT * FROM People WHERE Age > $ARGV[0]" ); $sth->execute(); my $fields = $sth->{NUM_OF_FIELDS}; my $rows = $sth->rows(); print "Selected $rows row(s) with $fields field(s)\n"; for ( 1 .. $rows ) { my ($id, $name, $age) = $sth->fetchrow(); print "$id $name $age\n"; } $sth->finish(); $dbh->disconnect();
Having set up the Dockerfile and the Perl scripts, we can now build the image
mymod/httpd:v3
and create an instance of this container named web
, which is linked to the db
container and which uses the standard HTTP server port (80) on the host:#docker build -t="mymod/httpd:v3" /var/docker_projects/mymod/httpd2
Uploading context 142.8 kB Uploading context Step 0 : FROM oraclelinux:6.6 ---> d56e767abb61 Step 1 : ENV http_proxy http://proxy.mydom.com:80 ---> Using cache ---> f92df8c449eb ... Step 11 : ENTRYPOINT /usr/sbin/httpd -D FOREGROUND ---> Running in 3203c57a7204 ---> 10dc2d7624d3 Removing intermediate container 3203c57a7204 Successfully built 10dc2d7624d3 #docker run -d --name web -p 80:80 --link db:db mymod/httpd:v3
ba8816c540513a892aa89828b5cf33464a7bb4616b56177266033d3311d0e00d
Finally, we can use curl to test the operation of the CGI scripts:
$curl http://10.0.0.2/cgi-bin/version.pl
Version = 5.1.73-log $curl http://10.0.0.2/cgi-bin/initdb.pl
Rows inserted in People table 1 Alice 42 2 Bobby 27 3 Carol 29 4 Daisy 20 5 Eddie 35 6 Frank 21 $curl http://10.0.0.2/cgi-bin/doquery.pl?30
Selected 2 row(s) with 3 field(s) 1 Alice 42 5 Eddie 35 $curl http://10.0.0.2/cgi-bin/doquery.pl?21
Selected 4 row(s) with 3 field(s) 1 Alice 42 2 Bobby 27 3 Carol 29 5 Eddie 35
Comentarios
Publicar un comentario