How to configure docker container proxy? - docker

I am newbie for docker. I try set a proxy for debian:jessie image but i didnt make it. I follow this link . I apply all of them with cat tag (example: 'cat > proxy.sh' , because vi or another editor not installed ) but there is some error about my proxy in apt-get update command.
Error Photo
My proxy : http://username:password#proxy2.domain.com

You can set the proxy environment variables when starting the container, for example:
docker container run \
-e HTTP_PROXY=http://username:password#proxy2.domain.com \
-e HTTPS_PROXY=http://username:password#proxy2.domain.com \
myimage
If you want the proxy-server to be automatically used when starting a container, you can configure default proxy-servers in the Docker CLI configuration file (~/.docker/config.json). You can find instructions for this in the networking section in the user guide.
For example:
{
"proxies": {
"default": {
"httpProxy": "http://username:password#proxy2.domain.com",
"httpsProxy": "http://username:password#proxy2.domain.com"
}
}
}
To verify if the ~/.docker/config.json configuration is working, start a container and print its env:
docker container run --rm busybox env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=220e4df13604
HTTP_PROXY=http://username:password#proxy2.domain.com
http_proxy=http://username:password#proxy2.domain.com
HTTPS_PROXY=http://username:password#proxy2.domain.com
https_proxy=http://username:password#proxy2.domain.com
HOME=/root

you need instruct the apt script to connect through proxy inside the container
# echo 'Acquire::http::proxy "proxy:port/";' > /etc/apt/apt.conf.d/40proxy
remember, this should be written inside the container
and in the machine that have docker running, the proxy should be configured like people said before in their comments

Related

How to make docker container connect everything through proxy

I know it is possible to pass http_proxy and https_proxy environment variables to a container as shown in eg. this SO answer. However, this only works for proxy-aware commands like wget and curl as they merely read and use these environment variables.
I need to connect everything through the proxy, so that all internet access is routed via the proxy. Essentially, the proxy should be transformed into a kind of VPN.
I am thinking about something similar to the --net=container option where the container gets its network from another container.
How do I configure a container to run everything through the proxy?
Jan Garaj's comment actually pointed me in the right direction.
As noted in my question, not all programs and commands use the proxy environment variables so simply passing the http_proxy and https_proxy env vars to docker is not a solution. I needed a solution where the whole docker container is directing every network requests (on certain ports) through the proxy. No matter which program or command.
The Medium article demonstrates how to build and setup a docker container that, by the help of redsocks, will redirect all ftp requests to another running docker container acting as a proxy. The communication between the containers is done via a docker network.
In my case I already have a running proxy so I don't need a docker network and a docker proxy. Also, I need to proxy http and https, not ftp.
By changing the configuration files I got it working. In this example I simply call wget ipecho.net/plain to retrieve my outside IP. If it works, this should be the IP of the proxy, not my real IP.
Configuration
Dockerfile:
FROM debian:latest
LABEL maintainer="marlar"
WORKDIR /app
ADD . /app
RUN apt-get update
RUN apt-get upgrade -qy
RUN apt-get install iptables redsocks curl wget lynx -qy
COPY redsocks.conf /etc/redsocks.conf
ENTRYPOINT /bin/bash run.sh
setup script (run.sh):
#!/bin/bash
echo "Configuration:"
echo "PROXY_SERVER=$PROXY_SERVER"
echo "PROXY_PORT=$PROXY_PORT"
echo "Setting config variables"
sed -i "s/vPROXY-SERVER/$PROXY_SERVER/g" /etc/redsocks.conf
sed -i "s/vPROXY-PORT/$PROXY_PORT/g" /etc/redsocks.conf
echo "Restarting redsocks and redirecting traffic via iptables"
/etc/init.d/redsocks restart
iptables -t nat -A OUTPUT -p tcp --dport 80 -j REDIRECT --to-port 12345
iptables -t nat -A OUTPUT -p tcp --dport 443 -j REDIRECT --to-port 12345
echo "Getting IP ..."
wget -q -O- https://ipecho.net/plain
redsocks.conf:
base {
log_debug = off;
log_info = on;
log = "file:/var/log/redsocks.log";
daemon = on;
user = redsocks;
group = redsocks;
redirector = iptables;
}
redsocks {
local_ip = 127.0.0.1;
local_port = 12345;
ip = vPROXY-SERVER;
port = vPROXY-PORT;
type = http-connect;
}
Building the container
build -t proxy-via-iptables .
Running the container
docker run -i -t --privileged -e PROXY_SERVER=x.x.x.x -e PROXY_PORT=xxxx proxy-via-iptables
Replace the proxy server and port with the relevant numbers.
If the container works and uses the external proxy, wget should spit out the IP of the proxy even though the wget command does not use the -e use_proxy=yes option. If it doesn't work, it will give you your own IP. Or perhaps no IP at all, depending on how it fails.
You can use the proxy env var:
docker container run \
-e HTTP_PROXY=http://username:password#proxy2.domain.com \
-e HTTPS_PROXY=http://username:password#proxy2.domain.com \
yourimage
If you want the proxy-server to be automatically used when starting a container, you can configure default proxy-servers in the Docker CLI configuration file (~/.docker/config.json). You can find instructions for this in the networking section in the user guide
for exemple :
{
"proxies": {
"default": {
"httpProxy": "http://username:password#proxy2.domain.com",
"httpsProxy": "http://username:password#proxy2.domain.com"
}
}
}
To verify if the ~/.docker/config.json configuration is working, start a container and print its env:
docker container run --rm busybox env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=220e4df13604
HTTP_PROXY=http://username:password#proxy2.domain.com
http_proxy=http://username:password#proxy2.domain.com
HTTPS_PROXY=http://username:password#proxy2.domain.com
https_proxy=http://username:password#proxy2.domain.com
HOME=/root

Dokcer - Changing permissions of /etc/hosts in docker file gives error [duplicate]

I want to update my /etc/hosts file during "docker build".
I added below line in Dockerfile but it's neither updating /etc/hosts file nor giving any error.
RUN echo "192.168.33.11 mynginx" >> /etc/hosts
I need to update /etc/hosts. Can anyone suggest on this?
With a more recent version of docker, this could be done with docker-compose and its extra_hosts directive
Add hostname mappings.
Use the same values as the docker run client --add-host parameter (which should already be available for docker 1.8).
extra_hosts:
- "somehost:162.242.195.82"
- "otherhost:50.31.209.229"
In short: modify /etc/hosts of your container when running it, instead of when building it.
With Docker 17.x+, you have a docker build --add-host mentioned below, but, as commented in issue 34078 and in this answer:
The --add-host feature during build is designed to allow overriding a host during build, but not to persist that configuration in the image.
The solutions mentioned do refer the docker-compose I was suggesting above:
Run an internal DNS; you can set the default DNS server to use in the daemon; that way every container started will automatically use the configured DNS by default
Use docker compose and provide a docker-compose.yml to your developers.
The docker compose file allows you to specify all the options that should be used when starting a container, so developers could just docker compose up to start the container with all the options they need to set.
You can not modify the host file in the image using echo in RUN step because docker daemon will maintain the file(/etc/hosts) and its content(hosts entry) when you start a container from the image.
However following can be used to achieve the same:
ENTRYPOINT ["/bin/sh", "-c" , "echo 192.168.254.10 database-server >> /etc/hosts && echo 192.168.239.62 redis-ms-server >> /etc/hosts && exec java -jar ./botblocker.jar " ]
Key to notice here is the use of exec command as docker documentation suggests. Use of exec will make the java command as PID 1 for the container. Docker interrupts will only respond to that.
See https://docs.docker.com/engine/reference/builder/#entrypoint
I think docker recently added the --add-host flag to docker build which is really great.
[Edit]
So this feature was updated on 17.04.0-ce
For more detail on how to use docker build with the --add-host flag please visit: https://docs.docker.com/edge/engine/reference/commandline/build/
Since this still comes up as a first answer in Google I'll contribute possible solution.
Command taken from here suprisingly worked for me (Docker 1.13.1, Ubuntu 16.04) :
docker exec -u 0 <container-name> /bin/sh -c "echo '<ip> <name>' >> /etc/hosts"
You can do with the following command at the time of running docker
docker run [OPTIONS] --add-host example.com:127.0.0.1 <your-image-name>:<your tag>
Here I am mapping example.com to localhost 127.0.0.1 and its working.
If this is useful for anyone, the HOSTALIASES env variable worked for me:
echo "fakehost realhost" > /etc/host.aliases
export HOSTALIASES=/etc/host.aliases
You can use the --add-host option during docker run.
For your case use:
docker run --add-host mynginx:192.168.33.11 [image_name]:[tag]
This will update your /etc/hosts
you can check it by using following commands:
docker exec -it [container_id] sh
if sh doesnt work for you ,then you can try bash or /bin/sh or /bin/bash
cat /etc/hosts
I just created a sh script and run it on start docker.
In this script I start all the services and update the hosts file:
on Dockerfile:
CMD /tmp/init_commands.sh & sleep infinity
init_comands.sh
any other commands...
echo "192.168.11.5 XXXXXXX" >> /etc/hosts
echo "192.168.11.6 XXXXXXY" >> /etc/hosts
echo "192.168.11.7 XXXXXXZ" >> /etc/hosts
Following worked for me by mounting the file during docker run instead of docker build
docker service create --name <name> --mount type=bind,source=/etc/hosts,dst=/etc/hosts <image>
Tis is me Dockefile
FROM XXXXX
ENV DNS_1="10.0.0.1 TEST1.COM"
ENV DNS_1="10.0.0.1 TEST2.COM"
CMD ["bash","change_hosts.sh"]`
#cat change_hosts.sh
su - root -c "env | grep DNS | akw -F "=" '{print $2}' >> /etc/hosts"
info
user must su
Just a quick answer to run your container using:
docker exec -it <container name> /bin/bash
once the container is open:
cd ..
then
`cd etc`
and then you can
cat hosts
or:
apt-get update
apt-get vim
or any editor you like and open it in vim, here you can modify say your startup ip to 0.0.0.0

Docker port not being exposed

Using Windows and I have pulled the Jenkins image successfully via
docker pull jenkins
I am running a new container via following command and it seems to start the container fine. But when I try to access the Jenkins page on my browser, I just get following error message. I was expecting to see the Jenkins main log in page. Same issue when I tried other images like Redis, Couchbase and JBoss/Wildfly. What am I doing wrong? New to Docker and following tutorials which has described the following command to expose ports. Same for some answers given here + docs. Please advice. Thanks.
docker run -tid -p 127.0.0.1:8097:8097 --name jen1 --rm jenkins
In browser, just getting a normal 'Problem Loading page Error'.
The site could be temporarily unavailable or too busy.
First, it looks a little bit strange use -tid. Since you're trying to run it detached, maybe, it'd be better just -d, and use -ti for example to access via shell docker exec -ti jen1 bash.
Second, docker localhost is not the same than host localhost, so, I'd run the container directly without 127.0.0.1. If you want to use it, you may specify --net=host, what makes 127.0.0.1 is the same inside and outside docker.
Third, try to access first through port 8080 for initial admin password.
Definitively, in summary:
docker run -d -p 8097:8080 --name jen1 --rm jenkins
Then,
http://172.17.0.2:8080/
Finally, unlock Jenkins setting admin password. You can have a look at starting logs: docker logs jen1
Take a look at Jenkins Dockerfile from here:
FROM openjdk:8-jdk
RUN apt-get update && apt-get install -y git curl && rm -rf /var/lib/apt/lists/*
ARG user=jenkins
ARG group=jenkins
ARG uid=1000
ARG gid=1000
ARG http_port=8080
ARG agent_port=50000
.....
.....
# for main web interface:
EXPOSE ${http_port}
# will be used by attached slave agents:
EXPOSE ${agent_port}
As you can see port 8080 is being exposed and not 8097.
Change your command to
docker run -tid -p 8097:8080 --name jen1 --rm jenkins
What your command does is connects your host port 8097 with jenkins image port 8097, but how do you know that the image exposes/uses port 8097 (spoiler: it doesn't).
This image uses port 8080, so you want to port your local 8097 to port that one.
Change the command to this:
docker run -tid -p 127.0.0.1:8097:8080 --name jen1 --rm jenkins
Just tested your command with this small fix, and it works locally for me.

Is there a way to make docker config editable from inside a container?

I have to start each instance of my application as a separate Docker service. The base image is the same but the configuration file is different for each instance. Now, the problem is my application makes some changes to the configuration file. And I want the configuration changes to persist so that when my application restarts (as docker service), it uses the updated configuration.
I am able to use the config file as a mount point using docker config. But the problem is no matter what mode (rwx) I give, I am not able to update the config file from inside the container. The mounted config is always Read-only file system.
1. How do I make the changes to the config file from docker container?
2. How do I make the updated config file persist outside the container, so that on service restart, the updated configuration is used?
I did the following to decouple config file from the image/container:
docker config create my-config config.txt
docker service create \
--name redis \
--config src=my-config,target=/config.txt,mode=0660 \
redis:alpine
docker container exec -ti <containerId> /bin/sh
The config file is mounted at /config.txt but I am not able to edit it.
The config will be read only by design. But you can copy this to another file inside your container as part of an entrypoint script defined in your image.
docker config create my-config config.txt
docker service create \
--name redis \
--config src=my-config,target=/config.orig,mode=0660 \
username/redis:custom
The entrypoint script would include the following:
if [ ! -f /config.txt -a -f /config.orig ];
cp /config.orig /config.txt
fi
# skipping the typical exec command here since redis has its own entrypoint
# exec "$#" # run the CMD as pid 1
exec docker-entrypoint.sh "$#"
Your Dockerfile to build that image would look like:
FROM redis:alpine
COPY /entrypoint.sh /
ENTRYPOINT [ "/entrypoint.sh" ]
And you'd build that with:
docker build -t username/redis:custom .
Docker swarm configs are read-only, not only from inside the container but also from the outside. to update the config of your service you must create a new config as explained in the docker swarm config docs
How do I update the config of my service?
You need to to copy the config, edit it, save it with new name, and then update the service
# Get the config from docker to file
docker config inspect --pretty my-config | tail -n +6 > conf-file
# Edit conf-file as needed here
...
# Save it with new name
docker config create my-config-v2 conf-file
# Update the service
docker service update \
--config-rm my-config \
--config-add source=my-config-v2,target=/config.txt \
redis:alpine
How do I update the config from inside the container?
For this you'll need to have access to docker from inside the container. you can do so by mounting the docker executable and the docker sock to the container:
docker run -it -v /var/run/docker.sock:/var/run/docker.sock \
-v /usr/bin/docker:/usr/bin/docker \
ubuntu bash

How to update /etc/hosts file in Docker image during "docker build"

I want to update my /etc/hosts file during "docker build".
I added below line in Dockerfile but it's neither updating /etc/hosts file nor giving any error.
RUN echo "192.168.33.11 mynginx" >> /etc/hosts
I need to update /etc/hosts. Can anyone suggest on this?
With a more recent version of docker, this could be done with docker-compose and its extra_hosts directive
Add hostname mappings.
Use the same values as the docker run client --add-host parameter (which should already be available for docker 1.8).
extra_hosts:
- "somehost:162.242.195.82"
- "otherhost:50.31.209.229"
In short: modify /etc/hosts of your container when running it, instead of when building it.
With Docker 17.x+, you have a docker build --add-host mentioned below, but, as commented in issue 34078 and in this answer:
The --add-host feature during build is designed to allow overriding a host during build, but not to persist that configuration in the image.
The solutions mentioned do refer the docker-compose I was suggesting above:
Run an internal DNS; you can set the default DNS server to use in the daemon; that way every container started will automatically use the configured DNS by default
Use docker compose and provide a docker-compose.yml to your developers.
The docker compose file allows you to specify all the options that should be used when starting a container, so developers could just docker compose up to start the container with all the options they need to set.
You can not modify the host file in the image using echo in RUN step because docker daemon will maintain the file(/etc/hosts) and its content(hosts entry) when you start a container from the image.
However following can be used to achieve the same:
ENTRYPOINT ["/bin/sh", "-c" , "echo 192.168.254.10 database-server >> /etc/hosts && echo 192.168.239.62 redis-ms-server >> /etc/hosts && exec java -jar ./botblocker.jar " ]
Key to notice here is the use of exec command as docker documentation suggests. Use of exec will make the java command as PID 1 for the container. Docker interrupts will only respond to that.
See https://docs.docker.com/engine/reference/builder/#entrypoint
I think docker recently added the --add-host flag to docker build which is really great.
[Edit]
So this feature was updated on 17.04.0-ce
For more detail on how to use docker build with the --add-host flag please visit: https://docs.docker.com/edge/engine/reference/commandline/build/
Since this still comes up as a first answer in Google I'll contribute possible solution.
Command taken from here suprisingly worked for me (Docker 1.13.1, Ubuntu 16.04) :
docker exec -u 0 <container-name> /bin/sh -c "echo '<ip> <name>' >> /etc/hosts"
You can do with the following command at the time of running docker
docker run [OPTIONS] --add-host example.com:127.0.0.1 <your-image-name>:<your tag>
Here I am mapping example.com to localhost 127.0.0.1 and its working.
If this is useful for anyone, the HOSTALIASES env variable worked for me:
echo "fakehost realhost" > /etc/host.aliases
export HOSTALIASES=/etc/host.aliases
You can use the --add-host option during docker run.
For your case use:
docker run --add-host mynginx:192.168.33.11 [image_name]:[tag]
This will update your /etc/hosts
you can check it by using following commands:
docker exec -it [container_id] sh
if sh doesnt work for you ,then you can try bash or /bin/sh or /bin/bash
cat /etc/hosts
I just created a sh script and run it on start docker.
In this script I start all the services and update the hosts file:
on Dockerfile:
CMD /tmp/init_commands.sh & sleep infinity
init_comands.sh
any other commands...
echo "192.168.11.5 XXXXXXX" >> /etc/hosts
echo "192.168.11.6 XXXXXXY" >> /etc/hosts
echo "192.168.11.7 XXXXXXZ" >> /etc/hosts
Following worked for me by mounting the file during docker run instead of docker build
docker service create --name <name> --mount type=bind,source=/etc/hosts,dst=/etc/hosts <image>
Tis is me Dockefile
FROM XXXXX
ENV DNS_1="10.0.0.1 TEST1.COM"
ENV DNS_1="10.0.0.1 TEST2.COM"
CMD ["bash","change_hosts.sh"]`
#cat change_hosts.sh
su - root -c "env | grep DNS | akw -F "=" '{print $2}' >> /etc/hosts"
info
user must su
Just a quick answer to run your container using:
docker exec -it <container name> /bin/bash
once the container is open:
cd ..
then
`cd etc`
and then you can
cat hosts
or:
apt-get update
apt-get vim
or any editor you like and open it in vim, here you can modify say your startup ip to 0.0.0.0

Resources