Hello everyone,
I'm currently trying to run a very simple server using SwiftNIO inside of a docker container.
The code looks like this, it just prints out any message that is received:
import NIO
final class Handler: ChannelInboundHandler {
typealias InboundIn = ByteBuffer
typealias OutboundOut = ByteBuffer
func channelRead(context: ChannelHandlerContext, data: NIOAny) {
let inBuffer = self.unwrapInboundIn(data)
guard let string = inBuffer.getString(at: 0, length: inBuffer.readableBytes), !string.isEmpty else { return }
print(string)
}
}
let group = MultiThreadedEventLoopGroup(numberOfThreads: System.coreCount)
let bootstrap = ServerBootstrap(group: group)
.serverChannelOption(ChannelOptions.backlog, value: 256)
.serverChannelOption(ChannelOptions.socketOption(.so_reuseaddr), value: 1)
.childChannelInitializer { channel in
channel.pipeline.addHandlers([BackPressureHandler(), Handler()])
}
.childChannelOption(ChannelOptions.socketOption(.so_reuseaddr), value: 1)
.childChannelOption(ChannelOptions.maxMessagesPerRead, value: 1)
.childChannelOption(ChannelOptions.recvAllocator, value: AdaptiveRecvByteBufferAllocator())
defer {
try! group.syncShutdownGracefully()
}
let channel: Channel
do {
channel = try bootstrap.bind(host: "127.0.0.1", port: 8080).wait()
print("Running server on:", channel.localAddress!)
} catch {
fatalError("Could not bind server: \(error)")
}
do {
try channel.closeFuture.wait()
} catch {
fatalError(error.localizedDescription)
}
This works fine when I'm running the server both on macOS and on my standard Ubuntu 18.04 installation. I can do ncat localhost 8080
or whatever and it prints out everything I send it.
However, when I try to run the same code inside of a docker container (using an Ubuntu 18.04 image), it behaves very strangely. The server still seems to start up correctly and prints Running server on: [IPv4]127.0.0.1/127.0.0.1:8080
. I can also connect to it using ncat
(meaning ncat
doesn't give me an error like Connection refused
that you would get if there was no server running under 127.0.0.1:8080
), but it doesn't seem to get any of my messages. It doesn't even run the closure I provided with childChannelInitializer
.
Am I doing something wrong?
For completeness here is my Dockerfile
:
FROM swift:5.6.1 AS builder
WORKDIR /usr/src/app
COPY . .
RUN swift build -c release
FROM swift:5.6.1-slim AS runner
WORKDIR /usr/bin
COPY --from=builder /usr/src/app/.build/release/NIOTest /usr/bin/NIOTest
EXPOSE 8080
CMD [ "/usr/bin/NIOTest" ]
I build the docker container using
sudo docker build -t nio-test .
and run it using
sudo docker run -tp 8080:8080 nio-test
which should work since I tested the procedure with server frameworks in other languages.
I even wrote a server in swift using manual calls to socket()
etc. and it works fine with the same setup. Just my NIO server refuses to work.
Does anyone have a clue what could be the issue?
Thanks in advance for your help!