Funnily enough I'm also wanting to export my Factorio server logs. Here's what I've got working.
Create a raw socket server (not WebSocket). You can run this remotely, on the host, or in another container.
I recommend UDP, as TCP seems to miss some messages during container shutdown, but both work similarly.
Change the log driver of the container you want to export the logs from to use syslog
(see the Docker docs). Set the syslog-address
to your socket server.
services:
my-server:
# ...
logging:
driver: syslog
options:
syslog-address: "udp://syslog-socket-server:9002"
syslog-format: "rfc5424"
Start up both the socket server and your container: et voilà! The socket server will now receive the logs of the container, and you can forward them as required.
There are many benefits to this method:
Example output
Here's an example of what my socket server prints
[SyslogSocketServer] started listening: InetSocketAddress(hostname=127.0.0.1, port=9002)
[SyslogSocketServer] received msg: <27>1 2022-06-26T17:28:07Z docker-desktop f22cae36b987 926 f22cae36b987 - + FACTORIO_VOL=/factorio
[SyslogSocketServer] received msg: <27>1 2022-06-26T17:28:07Z docker-desktop f22cae36b987 926 f22cae36b987 - + LOAD_LATEST_SAVE=true
[SyslogSocketServer] received msg: <27>1 2022-06-26T17:28:07Z docker-desktop f22cae36b987 926 f22cae36b987 - + GENERATE_NEW_SAVE=false
[SyslogSocketServer] received msg: <27>1 2022-06-26T17:28:07Z docker-desktop f22cae36b987 926 f22cae36b987 - + SAVE_NAME=
[SyslogSocketServer] received msg: <27>1 2022-06-26T17:28:07Z docker-desktop f22cae36b987 926 f22cae36b987 - + mkdir -p /factorio
[SyslogSocketServer] received msg: <27>1 2022-06-26T17:28:07Z docker-desktop f22cae36b987 926 f22cae36b987 - + mkdir -p /factorio/saves
[SyslogSocketServer] received msg: <27>1 2022-06-26T17:28:07Z docker-desktop f22cae36b987 926 f22cae36b987 - + mkdir -p /factorio/config
[SyslogSocketServer] received msg: <27>1 2022-06-26T17:28:07Z docker-desktop f22cae36b987 926 f22cae36b987 - + mkdir -p /factorio/mods
[SyslogSocketServer] received msg: <27>1 2022-06-26T17:28:07Z docker-desktop f22cae36b987 926 f22cae36b987 - + mkdir -p /factorio/scenarios
[SyslogSocketServer] received msg: <27>1 2022-06-26T17:28:07Z docker-desktop f22cae36b987 926 f22cae36b987 - + mkdir -p /factorio/script-output
Implementation
I'll give a very brief overview of my implementation.
Socket server
I've used Kotlin 1.7.0 and Ktor 2.0.2 for the socket server - but any other language will do just fine.
The socket server is based on the example in the Ktor docs. It
import io.ktor.network.selector.SelectorManager
import io.ktor.network.sockets.*
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
class SyslogSocketServer(
socketHostname: String = "127.0.0.1",
socketPort: Int = 9002,
) {
private val selectorManager: SelectorManager = SelectorManager(Dispatchers.IO)
// create a UDP server socket - it will listen to logs from Docker
private val serverSocketUdp: BoundDatagramSocket = aSocket(selectorManager)
.udp()
.bind(localAddress = InetSocketAddress(socketHostname, socketPort))
suspend fun start() = coroutineScope {
println("SyslogSocketServer is listening at ${serverSocketUdp.localAddress}")
serverSocketUdp.incoming.receiveAsFlow()
.onEach {
val msg = it.packet.readText()
println("[SyslogSocketServer] received msg: $msg")
}.launchIn(this)
}
}
suspend fun main() {
val syslogSocketServer = SyslogSocketServer()
syslogSocketServer.start()
}
Example logging driver settings
Here's how I configured my Factorio server using Docker Compose.
Note that I used host.docker.internal
(read more here) as I'm running my socket server on the host, not in another container.
version: "3.9"
services:
factorio-server:
image: factoriotools/factorio
container_name: "factorio-server"
ports:
- "34197:34197/udp" # factorio
- "27015:27015/tcp" # rcon
logging:
driver: syslog
options:
syslog-address: "udp://host.docker.internal:9002"
syslog-format: "rfc5424"