gramjs icon indicating copy to clipboard operation
gramjs copied to clipboard

Client not starting on Docker containerization

Open francestu96 opened this issue 1 year ago • 17 comments

I have this simple code:

const client = new TelegramClient(new StoreSession("my_session"), parseInt(process.env.API_ID), process.env.API_HASH, {
    connectionRetries: 5,
});

(async () => {
    await client.start({
        phoneNumber: async () => await input.text("Please enter your number: "),
        password: async () => await input.text("Please enter your password: "),
        phoneCode: async () => await input.text("Please enter the code you received: "),
        onError: (err) => console.log(err),
    });

    console.log("You should now be connected.");

    await client.sendMessage("me", { message: "test" });
    console.log("Sent to me.");
})()

It perfectly works without containerization. I want to create a Docker container with this code but it looks like it stucks on client.start function. This is the container log:

2024-02-08 17:42:34 [2024-02-08T16:42:34.106] [INFO] - [Running gramJS version 2.19.9]
2024-02-08 17:42:34 [2024-02-08T16:42:34.119] [INFO] - [Connecting to 91.108.56.132:80/TCPFull...]
2024-02-08 17:42:34 [2024-02-08T16:42:34.125] [INFO] - [Connection to 91.108.56.132:80/TCPFull complete!]
2024-02-08 17:42:34 [2024-02-08T16:42:34.134] [INFO] - [Using LAYER 166 for initial connect] 

It doesn't even print "You should now be connected". I took care of copying into the image also "my_session" in order to avoid the need to login again.

This is the Dockerfile:

FROM node:18-alpine

WORKDIR /telegrambot

COPY ./bot.js ./package.json .
COPY ./my_session ./my_session

RUN npm install

CMD [ "node", "bot.js" ]

What does it could be the problem?

Thank you in advance!

francestu96 avatar Feb 09 '24 16:02 francestu96

Having the exact same issue here.

Node Version v20.11.0 Docker Version 24.0.7

Inbell1s avatar Mar 06 '24 18:03 Inbell1s

i suppose that may be because of deprecated input(). You can try fixing it manually

alvvaysxxx avatar Apr 09 '24 05:04 alvvaysxxx

Still not working even with readline... Moreover, the input() is not supposed to be called since I copied the session and it doesn't need to call it

francestu96 avatar Apr 23 '24 10:04 francestu96

I even tried with a StringSession and used it to connect. Than called await client.start() without any parameters and it successfully connect, yet no way to proceed nor to add a listener for new messages... same output of before

Is it possible it is some Docker port mapping problem? This is getting me crazy

francestu96 avatar Apr 25 '24 14:04 francestu96

I have the same issue. I do not use any readline or something, because i send session from file directly, and call client.connect()

polRk avatar May 09 '24 22:05 polRk

Did you tried to run the docker image in interactive mode? I.e.

docker run -it image_name

PeterVoronov avatar Jun 02 '24 19:06 PeterVoronov

error: Not connected at /home/bun/app/node_modules/telegram/network/connection/Connection.js:71:15

polRk avatar Jun 20 '24 19:06 polRk

@francestu96 I have the same problem. Have you found any solutions to this issue?

coderFaiisal avatar Jun 25 '24 10:06 coderFaiisal

I have no problems at all with run in docker. Did you pass an API_ID nd API_HASH to docker? docker run -e API_ID='something' -e API_HASH='something' ... ?

PeterVoronov avatar Jun 25 '24 18:06 PeterVoronov

@PeterVoronov Could you please elaborate on this? Also, which version of gramjs are you using?

Here is logs error: WhatsApp Image 2024-06-21 at 8 22 06 PM (1)

I've been trying to connect to Telegram using the Gramjs TelegramClient in a worker thread. The worker hangs up to await client.connect() and after retries, it throws a connection error.

`import { Api, TelegramClient } from "telegram"; import accounts from "./accounts"; import redisClient from "./redis"; import { Worker } from "bullmq";

(async function init() { accounts.forEach((account, index) => { new Worker( message-queue-${index}, async (job) => { const { recipient, message } = job.data;

    console.log(`Processing job for recipient: ${recipient}`);

    const client = new TelegramClient(
      account.stringSession,
      account.apiId,
      account.apiHash,
      {
        connectionRetries: 5
      }
    );

    try {
      console.log("Connecting telegram client...");
      await client.connect();
      console.log("Telegram client connected...");

      await client.invoke(
        new Api.messages.SendMessage({
          peer: recipient,
          message: message,
          randomId: BigInt(`${Date.now()}`) as any,
          noWebpage: true,
          noforwards: true,
        })
      );

      console.log("Message sent...");
    } catch (error) {
      console.log("Failed to send message:", error);
    } finally {
      await client.disconnect();
      console.log("Telegram client disconnected...");
    }

    console.log(`Message sent...`);
  },
  {
    limiter: {
      max: 1,
      duration: 10000,
    },
    connection: redisClient,
  }
);

}); })();`

The application has been dockerized. Here is the docker-compose.yml.

docker-compose

DockerFile

Dockerfile

Finally, caddyfile for reverse proxy

Caddy

@PeterVoronov Any ideas?

Some observations:

I have checked the Docker network, and the containers are all connected, and I could ping Redis and Caddy from within the telegram. The Bullmq worker is also working fine.

coderFaiisal avatar Jun 27 '24 14:06 coderFaiisal

@PeterVoronov Could you please elaborate on this? Also, which version of gramjs are you using?

There is only one idea - I use after creation a client not a client.connect but cient.start. And for message sending i prefer to use clientsendMessage(peerId, messageParams)... P.S. And I can reommend to not reconnect each time, when do you receive a message. I,e, put client.start outside a workers.

PeterVoronov avatar Jun 27 '24 16:06 PeterVoronov

same issue here, any solution guys?

` await this.client.start({ phoneNumber: tgConfig.phoneNumber, password: async () => tgConfig.password, phoneCode: async () => await input.text("Please enter the code you received: "), onError: (err) => console.log(err.name + "stack error"), forceSMS: false, });

    console.log("telegram connected.");`

in local its connecting fine and all working but in docker environment it gives this output stucks here for a while and then crushed the docker program.

2024-02-08 17:42:34 [2024-02-08T16:42:34.106] [INFO] - [Running gramJS version 2.19.9]
2024-02-08 17:42:34 [2024-02-08T16:42:34.119] [INFO] - [Connecting to 91.108.56.132:80/TCPFull...]
2024-02-08 17:42:34 [2024-02-08T16:42:34.125] [INFO] - [Connection to 91.108.56.132:80/TCPFull complete!]
2024-02-08 17:42:34 [2024-02-08T16:42:34.134] [INFO] - [Using LAYER 166 for initial connect] 

hamakh11 avatar Aug 14 '24 13:08 hamakh11

As I said for me is the solution to make a first run of the docker in interactive mode:

docker run -it image_name -v docker_path:external_path -e ENV_VAR='somethin' comman_to_run_app

If you don't use the volume mapping inside the container - you can sipt -v docker_path:external_path, the same - for environment variables... Most important thing is the comman_to_run_app, which has to be equal to CMD comman_to_run_app from Dockerfile. I.e. if in docker file it is CMD npm run start, and no any volumes and environments, please try for the first run next command:

docker run -it image_name npm run start

PeterVoronov avatar Aug 14 '24 16:08 PeterVoronov

I tried the command you provided, which by running -it you can interact with the running image. and I guess this might fix the issues with having (input) to enter phone and password.

majority of people here have the telegram session already setup and they don't need input. the input is not the issue, there is something else. thanks,

hamakh11 avatar Aug 15 '24 06:08 hamakh11

@hamakh11 I recently encountered and resolved an issue with the Telegram client connection in a Docker environment, and I wanted to share my solution to help others who might face the same problem.

Problem When using the Telegram client in a Docker environment, I noticed that creating a new connection each time an API endpoint was hit caused the client to freeze or block. This happens because Telegram only allows one connection request per session. If multiple connections are attempted from the same account, it leads to issues, especially when handling multiple API requests. as Telegram authentication tokens (stringSession) do not expire on their own. They remain valid indefinitely unless one of the following conditions occurs:

  1. Account Deletion: The token becomes invalid if the associated Telegram account is deleted.
  2. Manual Logout: The token expires if the user logs out from the session.
  3. Inactivity: If the session is not used for 6 months, it will expire based on Telegram's inactivity policy.

Solution The key to solving this problem is to create the Telegram client connection only once and keep it persistent, similar to how you would handle a database connection. What you should have to do is generate a sessionString, store this string as a credential, and then use this sessionString, apiHash, and apiId as credentials to connect to the client. Here’s a detailed explanation:

Instead of creating a new Telegram client connection for each API request, establish the connection once the server starts. Maintain this connection for all subsequent operations. This prevents multiple connection attempts and ensures smooth communication with the Telegram API.

coderFaiisal avatar Aug 15 '24 07:08 coderFaiisal

thanks for your explanation,

I will try this, because every time that I wanted to connect to the telegram client I used the same session key that was generated on my local. I will try to generate the token on the docker client and then persist it.

hamakh11 avatar Aug 15 '24 07:08 hamakh11

I didn't know what is the problem. but using the same docker image in ubuntu 22.4 worked fine with no problems I can connect to telegram, but on windows docker I coudln't get it to work.

hamakh11 avatar Aug 19 '24 13:08 hamakh11