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:v2a47169154222329eed66762128755cd9fdd24d0f27ff8e0f678ef136bbc66d03 - Create a client container named
client1that runs the bash shell and is linked to thehttp_servercontainer:[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_serverasserver. 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 ~]#envHOSTNAME=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 serverPING 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.16PING 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://serverHTTP server running on guest [root@client1 ~]#curl http://172.17.0.16HTTP 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/hosts172.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 client2ping: unknown host client2 [root@client1 ~]#ping -c 1 172.17.0.18PING 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.cnfandrun.shfrom the/var/docker_projects/mymod/mysqldirectory to/etc/my.cnfand/opt/run.shin 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.6as a basis for the new image. RUN- Install the
mysql-serverpackage and make the/opt/run.shscript 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/mysqlUploading 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:v1ba8816c540513a892aa89828b5cf33464a7bb4616b56177266033d3311d0e00d
We next define a Dockerfile for the HTTP server, which we place in the
/var/docker_projects/mymod/httpd2directory: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/httpd2directory: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/httpd2Uploading 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:v3ba8816c540513a892aa89828b5cf33464a7bb4616b56177266033d3311d0e00d
Finally, we can use curl to test the operation of the CGI scripts:
$curl http://10.0.0.2/cgi-bin/version.plVersion = 5.1.73-log $curl http://10.0.0.2/cgi-bin/initdb.plRows 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?30Selected 2 row(s) with 3 field(s) 1 Alice 42 5 Eddie 35 $curl http://10.0.0.2/cgi-bin/doquery.pl?21Selected 4 row(s) with 3 field(s) 1 Alice 42 2 Bobby 27 3 Carol 29 5 Eddie 35
Comentarios
Publicar un comentario