How to connect to Rust server app that runs on Docker - docker

I am new in Rust and to study new language I have decided to write simple "server app" based on TcpListener. It's simple main function that looks like this:
fn main() {
println!("Start server");
let server = TcpListener::bind("127.0.0.1:7878").unwrap();
match server.accept() {
Ok((_socket, addr)) => {
println!("new client: {:?}", addr);
loop {
//do something
}
}
Err(e) => { println!("couldn't accept the client: {:?}", e) }
}
println!("server disconnect")
}
and also I have some client code that connect to listener
fn client() {
match TcpStream::connect("127.0.0.1:7878") {
Ok(mut stream) => {
println!("connect to server");
loop {
// do some work
}
}
Err(e) => { println!("couldn't connect to server: {:?}", e) }
}
println!("client disconnect")
}
When I run it from cmd everything works well but when I run it in docker conteiner I can not connect to listener
couldn't connect: Os { code: 10061, kind: ConnectionRefused, message:
"No connection could be made because the target machine actively
refused it." }
How can I fix it?
I am new in Docker as in Rust so if you need more information pls leave a comment.
Dockerfile:
FROM rust:1.50
WORKDIR /usr/src/appname
COPY . .
RUN cargo install --path .
RUN cargo build --release
CMD cargo run
to run docker container I use docker run --rm -dp 7878:7878 appname
after that when I run client code it returns ok but server does not react (I expect that "new client" message will appear)

Related

Trouble creating a FTP connection from within a docker container to an external host

So the setup is as followed:
I have a host machine on which i run a docker container. From this i want to open a connection to a ftp server on the web and download a test file. The programm is written in go and works when executed directly on the host machine without the container.
The minimum example script looks as follows and I use the ftp package github.com/jlaffaye/ftp: (This should work out of the box as is - at least it does for me)
package main
import (
"fmt"
"io/ioutil"
"log"
"strings"
"time"
"github.com/jlaffaye/ftp"
)
func main() {
URL := "ftp://speedtest.tele2.net/1MB.zip"
User := "anonymous"
Password := "anonymous"
urlElements := strings.Split(URL, "/")
dialTarget := fmt.Sprintf("%s:%s", urlElements[2], "21")
fmt.Println("Attempting FTP connection to ", dialTarget)
c, err := ftp.Dial(dialTarget, ftp.DialWithTimeout(5*time.Second))
if err != nil {
log.Fatalf("TCP dial failed: %v", err)
}
defer c.Quit()
err = c.Login(User, Password)
if err != nil {
log.Fatalf("FTP login failed: %v", err)
}
defer c.Logout()
data, err := c.Retr(strings.Join(urlElements[3:], "/"))
if err != nil {
log.Fatalf("Failed to get file: %v", err)
}
_, err = ioutil.ReadAll(data)
if err != nil {
log.Fatalf("Failed to read file: %v", err)
}
fmt.Println("success!")
}
Since this code part will be part of a larger container later on running this on the host network with --network=host in docker options is not possible. (Apart this did not work for some reason -> lead to timeouts or EOF errors on dial)
Solution I considered:
Open an ssh-bridge to the target machine. I tried this using the package github.com/elliotchance/sshtunnel which provides a (imo) comprehensive example of how to use it: See here for reference.
The idea was to basically tunnel from the container through the host directly onto the target. However while the tunnel returned a connection success, the ftp client still failed with timeouts or EOF errors.
For this reason: Is there a good way to do this? If so which direction would be the best to go in? I am somewhat lost on this, especially since since connecting an samba client to a remote machine works without any issue from within the container for some reason.
Thx in advance for any leads - please let me know if i missed to provide any information/details.
For reference the docker file looks like this:
FROM golang:alpine AS BUILDER
# install certificates to enable usage for http
RUN apk update \
&& apk upgrade \
&& apk add --no-cache \
ca-certificates \
&& update-ca-certificates 2>/dev/null || true
# all prerequsites should be done before this point.
WORKDIR /src
COPY . .
RUN go get -d -v
RUN CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=5 go build -o ./out/ftp-test .
FROM scratch
COPY --from=BUILDER /src/out/ftp-test /ftp-test
COPY --from=BUILDER /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
# Run the executable
ENTRYPOINT ["/ftp-test"]

DNS resolution failure error while connecting to grpc server running on docker

I am trying to access the grpc server which exposes 9000 port and is running as docker container.
I am using .net core client to connect to the server.It works perfectly fine when GRPC server is not running as a docker container.
I have tried using both the "localhost","dockerconatiner-ip" while creating the channel from client.I am running the grpc server on "0.0.0.0"and port 9000.
docker commands:
docker run -p 9000:9000 -a stdin -a stdout -it
Error:
Status(StatusCode=Unavailable, Detail="DNS resolution failed")
dockerfile:
FROM mcr.microsoft.com/dotnet/core/runtime:3.0
COPY Sample/bin/Release/netcoreapp3.0/publish/ app/
WORKDIR /app
EXPOSE 9000
ENTRYPOINT ["dotnet", "Sample.dll"]
Service Main:
static void Main(string[] args)
{
try
{
Environment.SetEnvironmentVariable("GRPC_VERBOSITY", "DEBUG");
const int Port = 9000;
Server server = new Server
{
Ports = { new ServerPort("0.0.0.0", 9000, ServerCredentials.Insecure) },
Services = { BindService(new TestService()) }
};
server.Start();
Console.WriteLine("starting server");
Console.WriteLine("Press any key to shut down");
Console.ReadKey();
server.ShutdownAsync().Wait();
Console.WriteLine("Grpc Server stopped");
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
}
Test service has a method to print received text to console.

How to run TestCafe runner class with Docker

I am new to TestCafe and want to run my testcases with runner class in Docker container.
I am able to run single testcase through Docker. But when i want to run with runner class, i am not able to do that.
I have followed this thread https://github.com/DevExpress/testcafe/issues/2761 but i don't know how to define "Environment initialization steps from the TestCafe Docker script in your runner."
my runner file
const testCafe = require('testcafe');
const fs = require('fs');
function runTest(tcOptions) {
testCafe('localhost', 8080, 8081)
.then(function(tc) {
let runner = tc.createRunner();
return runner
.src(['./apps/tests/*.test.js'])
.browsers(['firefox'])
.concurrency(4)
.reporter([
'list',
{
name: 'html',
output: './dist/testcafe/testCafe-report.html'
}
])
.screenshots('./dist/testcafe/testcafe-screenshots', true)
.run(tcOptions)
.catch(function(error) {
console.log(error);
});
})
.then(failedCount => {
if (failedCount > 0) console.log('Error Tests failed: ' + failedCount);
else console.log('All Desktop Tests Passed');
process.exit(0);
})
}
const tcOptions = {
debugMode: false
};
runTest(tcOptions);
and running this Docker command
docker run -v `pwd`/:/tests -e "NODE_PATH=/tests/node_modules" -it --entrypoint node testcafe/testcafe /tests/apps/testcafe//testcafe-desktop-run.js
{ Error: No tests to run. Either the test files contain no tests or the filter function is too restrictive.
at Bootstrapper._getTests (/tests/node_modules/testcafe/src/runner/bootstrapper.js:92:19) code: 'E1009', data: [] }
You need to define the full path to your test files or change your working directory to the /tests directory in the container.
Besides, this step is intended to run the in-memory display server. You may skip it if you are going to run tests in a headless browser.
Here is a command that works on my side with the Runner class:
docker run -v //c/Users/User/test-docker:/tests -w=/tests -it --entrypoint node testcafe/testcafe /tests/test-run.js

Connecting to docker container via telnet

I have a NET Core Console Application which has a socket binded to a port.
I have dockerized this application and i am trying to expose the binded port.The program shows its output correctly when i use docker attach [instance] .However when trying to connect with Telnet i get the error:
Error
$ telnet 127.0.0.1 20001
Connecting To 127.0.0.1...Could not open connection to the host, on port 8806: Connect failed
.NET Server
class Program {
public const int BUFFER_SIZE = 1024;
public const int EXPOSED_PORT = 20001;
public const string ADDRESS = "127.0.0.1";
public const int MAX_CONNECTIONS = 1;
public static ReadOnlyMemory<byte> CreateMessage(ReadOnlyMemory<byte>request) {
Memory<byte> response= Encoding.UTF8.GetBytes($"Response from Daemon:{DateTime.Now.ToString()}");
///------code------//
return response;
}
static async Task Main(string[] args) {
Memory<byte> buffer = ArrayPool<byte>.Shared.Rent(BUFFER_SIZE);
using (Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) {
serverSocket.Bind(new IPEndPoint(IPAddress.Parse(ADDRESS), EXPOSED_PORT));
Console.WriteLine($"Server started at {DateTime.Now.ToShortTimeString()} \r\nListening on port{EXPOSED_PORT}");
serverSocket.Listen(MAX_CONNECTIONS);
var client =await serverSocket.AcceptAsync();
while (true) {
int rxCount =await client.ReceiveAsync(buffer, SocketFlags.None);
if ((char) buffer.Span[0] == 'x'){
break;
}
await client.SendAsync(CreateMessage(buffer.Slice(0, rxCount)), SocketFlags.None);
}
}
ArrayPool<byte>.Shared.Return(buffer.ToArray());
}
}
Dockerfile
FROM microsoft/dotnet:latest
WORKDIR /app
COPY ./bin/Release/netcoreapp2.1/publish .
ENTRYPOINT [ "dotnet","DockerContainerDaemon.dll" ]
EXPOSE 20001
docker and build command script
dotnet build -c Release
dotnet publish
docker build --build-arg Port=20001 -t daemon .
docker stop inst1
docker rm inst1
docker run --name inst1 -p 20001:20001 -d daemon
Running docker -ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f675c3e502ad daemon "dotnet DockerContai…" 5 seconds ago Up 3 seconds 0.0.0.0:20001->20001/tcp inst1
P.S As someone pointed out i tried exposing with both 127.0.0.1 and 0.0.0.0 from the .NET Application. to no avail.
Try to bind the application to 0.0.0.0 instead of 127.0.0.1. This will solve your problem.

Can't run Go (lang) app from docker image on docker-machine (Virtual Box)

I have a very simple application. Here is the code:
package main
import (
"fmt"
"math/rand"
"time"
"net/http"
"encoding/base64"
"encoding/json"
)
type Message struct {
Text string `json:"text"`
}
var cookieQuotes = []string{
// Skipped all the stuff
}
const COOKIE_NAME = "your_cookie"
func main() {
http.HandleFunc("/set_cookie", setCookie)
http.HandleFunc("/get_cookie", getCookie)
http.Handle("/favicon.ico", http.NotFoundHandler())
http.ListenAndServe(":8080", nil)
}
func setCookie(w http.ResponseWriter, r *http.Request) {
quote := getRandomCookieQuote()
encQuote := base64.StdEncoding.EncodeToString([]byte(quote))
http.SetCookie(w, &http.Cookie{
Name: COOKIE_NAME,
Value: encQuote,
})
}
func getCookie(w http.ResponseWriter, r *http.Request) {
cookie, err := r.Cookie(COOKIE_NAME)
if err != nil {
fmt.Fprintln(w, "Cannot get the cookie")
}
message, _ := base64.StdEncoding.DecodeString(cookie.Value)
msg := Message{Text:string(message)}
fmt.Println(msg.Text)
respBody, err := json.Marshal(msg)
fmt.Println(string(respBody))
if err != nil {
fmt.Println("Cannot marshall JSON")
}
w.Header().Set("Content-Type", "application/json")
fmt.Fprintln(w, string(respBody))
}
func getRandomCookieQuote() string {
source := rand.NewSource(time.Now().UnixNano())
random := rand.New(source)
i := random.Intn(len(cookieQuotes))
return cookieQuotes[i]
}
It was tested locally, and, also I've tried to run a docker container with it on my machine (Ubuntu) and it was working perfectly. But I want to run it on Virtual Machine (I use Oracle Virtual Box).
So, I have installed docker-machine:
docker-machine version 0.12.2, build 9371605
After that, I've switched to it, like it was recommended in official documentation like this:
eval "$(docker-machine env default)"
So I can do now from a perspective of that machine.
Also I've tried to run ngnix from the documentation example:
docker run -d -p 8000:80 nginx
curl $(docker-machine ip default):8000
And I get the result, I can get to ngnix welcome page by accessing my docker machine ip-address which could be accessed by command:
docker-machine ip default
But when I try to run my own docker image, I could not do this. When I try to access it, I get:
curl $(docker-machine ip default):8080
curl: (7) Failed to connect to 192.168.99.100 port 8080: Connection refused
Also I've tried to skip a port, to add protocol (http, and even https for the sake of luck) - nothing works.
Maybe, something wrong with my Dockerfile?
# Go experiments with cookies
FROM golang:1.8-onbuild
MAINTAINER vasyania2#gmail.com
Could you help me please?
This command maps port 8080 from your docker host to port 80 of your container:
docker run -d -p 8080:80 cookie-app
This instruction tells your go application to listen on port 8080, inside the container:
http.ListenAndServe(":8080", nil)
You have a port mismatch in those above lines, your application is not listening on the port you are forwarding to.
To connect to port 8080 of your container, you can run the following:
docker run -d -p 8080:8080 cookie-app

Resources